]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'driver-core-4.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 26 Mar 2017 18:05:42 +0000 (11:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 26 Mar 2017 18:05:42 +0000 (11:05 -0700)
Pull driver core fix from Greg KH:
 "Here is a single kernfs fix for 4.11-rc4 that resolves a reported
  issue.

  It has been in linux-next with no reported issues"

* tag 'driver-core-4.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  kernfs: Check KERNFS_HAS_RELEASE before calling kernfs_release_file()

705 files changed:
Documentation/cgroup-v2.txt
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
Documentation/devicetree/bindings/display/exynos/samsung-fimd.txt
Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt [deleted file]
Documentation/devicetree/bindings/powerpc/4xx/emac.txt
Documentation/gcc-plugins.txt
Documentation/networking/ip-sysctl.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/am335x-pcm-953.dtsi
arch/arm/boot/dts/am57xx-idk-common.dtsi
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/bcm953012k.dts
arch/arm/boot/dts/bcm958522er.dts
arch/arm/boot/dts/bcm958525er.dts
arch/arm/boot/dts/bcm958525xmc.dts
arch/arm/boot/dts/bcm958622hr.dts
arch/arm/boot/dts/bcm958623hr.dts
arch/arm/boot/dts/bcm958625hr.dts
arch/arm/boot/dts/bcm988312hr.dts
arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
arch/arm/boot/dts/sama5d2.dtsi
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/ste-href.dtsi
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
arch/arm/configs/omap2plus_defconfig
arch/arm/mach-at91/pm.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/gpmc-nand.c [deleted file]
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/omap-headsmp.S
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/tools/syscall.tbl
arch/arm64/Kconfig
arch/arm64/boot/dts/broadcom/ns2.dtsi
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/cpuidle.c
arch/arm64/kernel/kaslr.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/mm/kasan_init.c
arch/openrisc/include/asm/cmpxchg.h
arch/openrisc/include/asm/uaccess.h
arch/openrisc/kernel/or32_ksyms.c
arch/openrisc/kernel/process.c
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/uaccess.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/module.c
arch/parisc/kernel/perf.c
arch/parisc/kernel/process.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/boot/zImage.lds.S
arch/powerpc/crypto/crc32c-vpmsum_glue.c
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/mce.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/idle_book3s.S
arch/powerpc/kernel/mce.c
arch/powerpc/kernel/mce_power.c
arch/powerpc/mm/init_64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/isa207-common.c
arch/powerpc/perf/isa207-common.h
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/lpar.c
arch/x86/events/core.c
arch/x86/include/asm/pgtable-3level.h
arch/x86/include/asm/pgtable.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
arch/x86/kernel/head64.c
arch/x86/kernel/nmi.c
arch/x86/kernel/tsc.c
arch/x86/kernel/unwind_frame.c
arch/x86/mm/kasan_init_64.c
arch/x86/mm/mpx.c
arch/x86/platform/intel-mid/device_libs/Makefile
arch/x86/platform/intel-mid/device_libs/platform_mrfld_power_btn.c [new file with mode: 0644]
arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c
arch/x86/platform/intel-mid/mfld.c
block/bio.c
block/blk-core.c
block/blk-mq-tag.c
block/blk-mq.c
block/blk-stat.c
crypto/af_alg.c
crypto/algif_hash.c
drivers/acpi/acpi_processor.c
drivers/acpi/bus.c
drivers/acpi/processor_core.c
drivers/acpi/spcr.c
drivers/ata/ahci_qoriq.c
drivers/ata/libata-sff.c
drivers/ata/libata-transport.c
drivers/base/core.c
drivers/bluetooth/Kconfig
drivers/char/hw_random/amd-rng.c
drivers/char/hw_random/geode-rng.c
drivers/char/hw_random/omap-rng.c
drivers/clk/clk.c
drivers/clk/rockchip/clk-rk3036.c
drivers/clk/sunxi-ng/Kconfig
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
drivers/clk/sunxi-ng/ccu_mp.c
drivers/clk/sunxi-ng/ccu_nkmp.c
drivers/clocksource/tcb_clksrc.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/sysfs.c
drivers/crypto/ccp/ccp-dev.c
drivers/crypto/ccp/ccp-dmaengine.c
drivers/crypto/s5p-sss.c
drivers/dax/dax.c
drivers/gpio/gpio-altera-a10sr.c
drivers/gpio/gpio-altera.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-xgene.c
drivers/gpu/drm/amd/acp/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/si_dpm.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
drivers/gpu/drm/arm/malidp_crtc.c
drivers/gpu/drm/arm/malidp_hw.c
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/arm/malidp_regs.h
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/gvt/aperture_gm.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/debug.h
drivers/gpu/drm/i915/gvt/edid.c
drivers/gpu/drm/i915/gvt/execlist.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mmio.c
drivers/gpu/drm/i915/gvt/mmio.h
drivers/gpu/drm/i915/gvt/opregion.c
drivers/gpu/drm/i915/gvt/render.c
drivers/gpu/drm/i915/gvt/sched_policy.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_context.h
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_object.h
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_csr.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_gvt.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_hotplug.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/hid/Kconfig
drivers/hid/hid-chicony.c
drivers/hid/hid-core.c
drivers/hid/hid-corsair.c
drivers/hid/hid-ids.h
drivers/hid/hid-sony.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/it87.c
drivers/hwmon/max31790.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
drivers/iio/magnetometer/ak8974.c
drivers/infiniband/core/cq.c
drivers/infiniband/core/device.c
drivers/infiniband/hw/i40iw/i40iw_utils.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
drivers/infiniband/sw/rdmavt/mmap.c
drivers/infiniband/sw/rxe/Kconfig
drivers/infiniband/sw/rxe/rxe_mmap.c
drivers/infiniband/sw/rxe/rxe_req.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/misc/cm109.c
drivers/input/misc/ims-pcu.c
drivers/input/misc/yealink.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/elan_i2c_core.c
drivers/input/rmi4/rmi_f30.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/tablet/hanwang.c
drivers/input/tablet/kbtab.c
drivers/input/touchscreen/sur40.c
drivers/iommu/amd_iommu.c
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/exynos-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/iommu.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/macintosh/macio_asic.c
drivers/md/dm.c
drivers/md/md-cluster.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/platform/coda/imx-vdoa.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/sti/bdisp/bdisp-v4l2.c
drivers/media/usb/dvb-usb/dvb-usb-firmware.c
drivers/memory/omap-gpmc.c
drivers/misc/cxl/pci.c
drivers/mmc/core/block.c
drivers/mmc/core/mmc.c
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/sdhci-of-arasan.c
drivers/mmc/host/sdhci-of-at91.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/ushc.c
drivers/net/ethernet/amd/xgbe/xgbe-common.h
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/aquantia/atlantic/aq_main.c
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/brocade/bna/bnad_debugfs.c
drivers/net/ethernet/cavium/liquidio/lio_main.c
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
drivers/net/ethernet/cavium/liquidio/octeon_config.h
drivers/net/ethernet/cavium/liquidio/octeon_droq.c
drivers/net/ethernet/cavium/liquidio/octeon_droq.h
drivers/net/ethernet/cavium/liquidio/octeon_main.h
drivers/net/ethernet/cavium/liquidio/octeon_network.h
drivers/net/ethernet/cavium/thunder/nic.h
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.h
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.h
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_iscsi.c
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_ooo.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/Makefile
drivers/net/fjes/fjes_main.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/marvell.c
drivers/net/phy/phy_device.c
drivers/net/phy/spi_ks8995.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wimax/i2400m/usb.c
drivers/net/wireless/ath/ath10k/hw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/marvell/mwifiex/main.c
drivers/net/wireless/marvell/mwifiex/pcie.c
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netback/xenbus.c
drivers/nvme/host/rdma.c
drivers/nvme/target/core.c
drivers/nvme/target/loop.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/rdma.c
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/phy-bcm-nsp-usb3.c [deleted file]
drivers/phy/phy-exynos-pcie.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/fujitsu-laptop.c
drivers/remoteproc/Kconfig
drivers/scsi/Kconfig
drivers/scsi/aacraid/src.c
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h
drivers/scsi/hpsa_cmd.h
drivers/scsi/libiscsi.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/lpfc/lpfc_nvme.h
drivers/scsi/lpfc/lpfc_nvmet.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mpt3sas/mpt3sas_base.h
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/qedf/qedf_dbg.h
drivers/scsi/qedf/qedf_fip.c
drivers/scsi/qedf/qedf_io.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qedi/qedi_debugfs.c
drivers/scsi/qedi/qedi_fw.c
drivers/scsi/qedi/qedi_gbl.h
drivers/scsi/qedi/qedi_iscsi.c
drivers/scsi/qedi/qedi_main.c
drivers/scsi/qla2xxx/Kconfig
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_dfs.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/sd.c
drivers/scsi/storvsc_drv.c
drivers/scsi/ufs/ufs.h
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h
drivers/scsi/vmw_pvscsi.c
drivers/staging/lustre/lnet/lnet/lib-socket.c
drivers/target/target_core_alua.c
drivers/target/target_core_configfs.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/st-asc.c
drivers/tty/tty_ldisc.c
drivers/usb/class/usbtmc.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_acm.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/f_uvc.c
drivers/usb/gadget/udc/pch_udc.c
drivers/usb/misc/idmouse.c
drivers/usb/misc/lvstest.c
drivers/usb/misc/uss720.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_dsps.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/wusbcore/wa-hc.c
drivers/uwb/hwa-rc.c
drivers/uwb/i1480/dfu/usb.c
drivers/vfio/vfio.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/vsock.c
drivers/xen/gntdev.c
drivers/xen/xen-acpi-processor.c
fs/afs/callback.c
fs/afs/cmservice.c
fs/afs/file.c
fs/afs/fsclient.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/misc.c
fs/afs/mntpt.c
fs/afs/rxrpc.c
fs/afs/security.c
fs/afs/server.c
fs/afs/vlocation.c
fs/afs/write.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/crypto/crypto.c
fs/crypto/fname.c
fs/crypto/fscrypt_private.h
fs/crypto/keyinfo.c
fs/crypto/policy.c
fs/dlm/lowcomms.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/move_extent.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/f2fs/debug.c
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/node.c
fs/f2fs/segment.c
fs/fs-writeback.c
fs/gfs2/incore.h
fs/jbd2/journal.c
fs/jbd2/revoke.c
fs/nfs/callback.c
fs/nfs/client.c
fs/nfs/filelayout/filelayoutdev.c
fs/nfs/flexfilelayout/flexfilelayout.h
fs/nfs/flexfilelayout/flexfilelayoutdev.c
fs/nfs/internal.h
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c
fs/nfs/write.c
fs/ocfs2/cluster/tcp.c
fs/xfs/libxfs/xfs_dir2_priv.h
fs/xfs/libxfs/xfs_dir2_sf.c
fs/xfs/libxfs/xfs_inode_fork.c
fs/xfs/libxfs/xfs_inode_fork.h
fs/xfs/xfs_dir2_readdir.c
fs/xfs/xfs_inode.c
include/crypto/if_alg.h
include/linux/acpi.h
include/linux/ccp.h
include/linux/dccp.h
include/linux/device.h
include/linux/errqueue.h
include/linux/filter.h
include/linux/fscrypt_common.h
include/linux/gpio/consumer.h
include/linux/hwmon.h
include/linux/iio/sw_device.h
include/linux/iommu.h
include/linux/kasan.h
include/linux/list_nulls.h
include/linux/mlx4/device.h
include/linux/net.h
include/linux/omap-gpmc.h
include/linux/phy.h
include/linux/rculist_nulls.h
include/linux/reset.h
include/linux/usb/quirks.h
include/linux/virtio_vsock.h
include/net/af_vsock.h
include/net/inet_common.h
include/net/inet_connection_sock.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nf_tables_ipv6.h
include/net/sctp/structs.h
include/net/sock.h
include/rdma/ib_verbs.h
include/scsi/libiscsi.h
include/scsi/scsi_device.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/uapi/asm-generic/unistd.h
include/uapi/drm/omap_drm.h
include/uapi/linux/btrfs.h
include/uapi/linux/packet_diag.h
include/uapi/rdma/mlx5-abi.h
include/video/exynos5433_decon.h
kernel/audit.c
kernel/audit.h
kernel/auditsc.c
kernel/bpf/hashtab.c
kernel/bpf/lpm_trie.c
kernel/cgroup/cgroup-v1.c
kernel/cgroup/pids.c
kernel/cpu.c
kernel/events/core.c
kernel/futex.c
kernel/locking/rwsem-spinlock.c
kernel/memremap.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/deadline.c
kernel/sched/loadavg.c
kernel/workqueue.c
mm/gup.c
mm/memory_hotplug.c
mm/percpu-vm.c
mm/percpu.c
mm/swap_slots.c
mm/vmalloc.c
mm/z3fold.c
net/atm/svc.c
net/ax25/af_ax25.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bat_v.c
net/batman-adv/fragmentation.c
net/batman-adv/gateway_common.c
net/batman-adv/soft-interface.c
net/batman-adv/types.h
net/bluetooth/l2cap_sock.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/bridge/br_fdb.c
net/bridge/br_input.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_private.h
net/ceph/messenger.c
net/core/dev.c
net/core/net-sysfs.c
net/core/netclassid_cgroup.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ccids/ccid2.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/minisocks.c
net/decnet/af_decnet.c
net/ipv4/af_inet.c
net/ipv4/fib_frontend.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_fragment.c
net/ipv4/ip_output.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
net/ipv4/netfilter/nft_masq_ipv4.c
net/ipv4/netfilter/nft_redir_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_timer.c
net/ipv6/af_inet6.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6_vti.c
net/ipv6/netfilter/nft_masq_ipv6.c
net/ipv6/netfilter/nft_redir_ipv6.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/irda/af_irda.c
net/iucv/af_iucv.c
net/llc/af_llc.c
net/mpls/af_mpls.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_nat_proto_sctp.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_ct.c
net/netfilter/nft_meta.c
net/netfilter/nft_nat.c
net/netfilter/nft_set_bitmap.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/netrom/af_netrom.c
net/nfc/llcp_sock.c
net/openvswitch/flow_netlink.c
net/phonet/pep.c
net/phonet/socket.c
net/rds/connection.c
net/rds/ib_cm.c
net/rds/rds.h
net/rds/tcp.c
net/rds/tcp.h
net/rds/tcp_listen.c
net/rose/af_rose.c
net/rxrpc/conn_event.c
net/rxrpc/input.c
net/rxrpc/recvmsg.c
net/rxrpc/sendmsg.c
net/sched/act_connmark.c
net/sched/act_skbmod.c
net/sched/sch_dsmark.c
net/sctp/associola.c
net/sctp/ipv6.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/protocol.c
net/sctp/socket.c
net/smc/af_smc.c
net/socket.c
net/sunrpc/xprtrdma/verbs.c
net/tipc/socket.c
net/tipc/subscr.c
net/unix/af_unix.c
net/unix/garbage.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/virtio_transport.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/nl80211.c
net/x25/af_x25.c
net/xfrm/xfrm_policy.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_fifo.c
sound/core/seq/seq_memory.c
sound/core/seq/seq_memory.h
sound/pci/ctxfi/cthw20k1.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/x86/Kconfig
tools/include/uapi/linux/bpf_perf_event.h [new file with mode: 0644]
tools/perf/util/symbol.c
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/test_maps.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/powerpc/include/vsx_asm.h

index 3b8449f8ac7e80a0ebeaf6dfe8c64b15503f3954..49d7c997fa1ee7f759b5ba319bb57be464f0bd47 100644 (file)
@@ -1142,16 +1142,17 @@ used by the kernel.
 
   pids.max
 
- A read-write single value file which exists on non-root cgroups.  The
- default is "max".
+       A read-write single value file which exists on non-root
      cgroups.  The default is "max".
 
- Hard limit of number of processes.
      Hard limit of number of processes.
 
   pids.current
 
- A read-only single value file which exists on all cgroups.
      A read-only single value file which exists on all cgroups.
 
- The number of processes currently in the cgroup and its descendants.
+       The number of processes currently in the cgroup and its
+       descendants.
 
 Organisational operations are not blocked by cgroup policies, so it is
 possible to have pids.current > pids.max.  This can be done by either
index 30c546900b6021d24d64e1033714d362f3152a0e..07dbb358182ccd255baf2ed1220d5df9044f9dd7 100644 (file)
@@ -45,7 +45,7 @@ The following clocks are available:
    - 1 15      SATA
    - 1 16      SATA USB
    - 1 17      Main
-   - 1 18      SD/MMC
+   - 1 18      SD/MMC/GOP
    - 1 21      Slow IO (SPI, NOR, BootROM, I2C, UART)
    - 1 22      USB3H0
    - 1 23      USB3H1
@@ -65,7 +65,7 @@ Required properties:
        "cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio",
        "cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none",
        "cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata",
-       "cpm-sata-usb", "cpm-main", "cpm-sd-mmc", "none", "none", "cpm-slow-io",
+       "cpm-sata-usb", "cpm-main", "cpm-sd-mmc-gop", "none", "none", "cpm-slow-io",
        "cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
 
 Example:
@@ -78,6 +78,6 @@ Example:
                gate-clock-output-names = "cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio",
                        "cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none",
                        "cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata",
-                       "cpm-sata-usb", "cpm-main", "cpm-sd-mmc", "none", "none", "cpm-slow-io",
+                       "cpm-sata-usb", "cpm-main", "cpm-sd-mmc-gop", "none", "none", "cpm-slow-io",
                        "cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
        };
index a78265993665a65bae524bb19606a7c16f248770..ca5204b3bc218bfe8e04a4fd5ca70482b1ab8c6b 100644 (file)
@@ -4,7 +4,6 @@ Required properties:
   - compatible: value should be one of the following
                "samsung,exynos3250-mipi-dsi" /* for Exynos3250/3472 SoCs */
                "samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
-               "samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */
                "samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
                "samsung,exynos5422-mipi-dsi" /* for Exynos5422/5800 SoCs */
                "samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
index 18645e0228b054e1ec0a77658c78d30f3c7eed8e..5837402c3adeae526a4e6efa914fd43c64c10443 100644 (file)
@@ -11,7 +11,6 @@ Required properties:
                "samsung,s5pv210-fimd"; /* for S5PV210 SoC */
                "samsung,exynos3250-fimd"; /* for Exynos3250/3472 SoCs */
                "samsung,exynos4210-fimd"; /* for Exynos4 SoCs */
-               "samsung,exynos4415-fimd"; /* for Exynos4415 SoC */
                "samsung,exynos5250-fimd"; /* for Exynos5250 SoCs */
                "samsung,exynos5420-fimd"; /* for Exynos5420/5422/5800 SoCs */
 
index ea9c1c9607f61239d2d0211d0cf5a607da406fb0..520d61dad6dd7ff4f65e5e8cddbf33a63b81b009 100644 (file)
@@ -13,7 +13,7 @@ Required Properties:
        - "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following,
                                                        before RK3288
        - "rockchip,rk3288-dw-mshc": for Rockchip RK3288
-       - "rockchip,rk1108-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK1108
+       - "rockchip,rv1108-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RV1108
        - "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3036
        - "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3368
        - "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
diff --git a/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt b/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
deleted file mode 100644 (file)
index e68ae5d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-Broadcom USB3 phy binding for northstar plus SoC
-The USB3 phy is internal to the SoC and is accessed using mdio interface.
-
-Required mdio bus properties:
-- reg: Should be 0x0 for SoC internal USB3 phy
-- #address-cells: must be 1
-- #size-cells: must be 0
-
-Required USB3 PHY properties:
-- compatible: should be "brcm,nsp-usb3-phy"
-- reg: USB3 Phy address on SoC internal MDIO bus and it should be 0x10.
-- usb3-ctrl-syscon: handler of syscon node defining physical address
-  of usb3 control register.
-- #phy-cells: must be 0
-
-Required usb3 control properties:
-- compatible: should be "brcm,nsp-usb3-ctrl"
-- reg: offset and length of the control registers
-
-Example:
-
-       mdio@0 {
-               reg = <0x0>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               usb3_phy: usb-phy@10 {
-                       compatible = "brcm,nsp-usb3-phy";
-                       reg = <0x10>;
-                       usb3-ctrl-syscon = <&usb3_ctrl>;
-                       #phy-cells = <0>;
-                       status = "disabled";
-               };
-       };
-
-       usb3_ctrl: syscon@104408 {
-               compatible = "brcm,nsp-usb3-ctrl", "syscon";
-               reg = <0x104408 0x3fc>;
-       };
index 712baf6c3e246fa9ea93c6bab4cb8f294b894d86..44b842b6ca154d9c13c3d0da6a784fe54195fcf9 100644 (file)
@@ -71,6 +71,9 @@
                          For Axon it can be absent, though my current driver
                          doesn't handle phy-address yet so for now, keep
                          0x00ffffff in it.
+    - phy-handle       : Used to describe configurations where a external PHY
+                         is used. Please refer to:
+                         Documentation/devicetree/bindings/net/ethernet.txt
     - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
                          operations (if absent the value is the same as
                          rx-fifo-size).  For Axon, either absent or 2048.
                          offload, phandle of the TAH device node.
     - tah-channel       : 1 cell, optional. If appropriate, channel used on the
                          TAH engine.
+    - fixed-link       : Fixed-link subnode describing a link to a non-MDIO
+                         managed entity. See
+                         Documentation/devicetree/bindings/net/fixed-link.txt
+                         for details.
+    - mdio subnode     : When the EMAC has a phy connected to its local
+                         mdio, which us supported by the kernel's network
+                         PHY library in drivers/net/phy, there must be device
+                         tree subnode with the following required properties:
+                               - #address-cells: Must be <1>.
+                               - #size-cells: Must be <0>.
 
-    Example:
+                         For PHY definitions: Please refer to
+                         Documentation/devicetree/bindings/net/phy.txt and
+                         Documentation/devicetree/bindings/net/ethernet.txt
+
+    Examples:
 
        EMAC0: ethernet@40000800 {
                device_type = "network";
                zmii-channel = <0>;
        };
 
+       EMAC1: ethernet@ef600c00 {
+               device_type = "network";
+               compatible = "ibm,emac-apm821xx", "ibm,emac4sync";
+               interrupt-parent = <&EMAC1>;
+               interrupts = <0 1>;
+               #interrupt-cells = <1>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               interrupt-map = <0 &UIC2 0x10 IRQ_TYPE_LEVEL_HIGH /* Status */
+                                1 &UIC2 0x14 IRQ_TYPE_LEVEL_HIGH /* Wake */>;
+               reg = <0xef600c00 0x000000c4>;
+               local-mac-address = [000000000000]; /* Filled in by U-Boot */
+               mal-device = <&MAL0>;
+               mal-tx-channel = <0>;
+               mal-rx-channel = <0>;
+               cell-index = <0>;
+               max-frame-size = <9000>;
+               rx-fifo-size = <16384>;
+               tx-fifo-size = <2048>;
+               fifo-entry-size = <10>;
+               phy-mode = "rgmii";
+               phy-handle = <&phy0>;
+               phy-map = <0x00000000>;
+               rgmii-device = <&RGMII0>;
+               rgmii-channel = <0>;
+               tah-device = <&TAH0>;
+               tah-channel = <0>;
+               has-inverted-stacr-oc;
+               has-new-stacr-staopc;
+
+               mdio {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       phy0: ethernet-phy@0 {
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                               reg = <0>;
+                       };
+               };
+       };
+
+
       ii) McMAL node
 
     Required properties:
     - revision           : as provided by the RGMII new version register if
                           available.
                           For Axon: 0x0000012a
-
index 891c694644348241925dc3e585d632222d8b0948..433eaefb4aa171ac62f3162866763a0526d7eb83 100644 (file)
@@ -18,8 +18,8 @@ because gcc versions 4.5 and 4.6 are compiled by a C compiler,
 gcc-4.7 can be compiled by a C or a C++ compiler,
 and versions 4.8+ can only be compiled by a C++ compiler.
 
-Currently the GCC plugin infrastructure supports only the x86, arm and arm64
-architectures.
+Currently the GCC plugin infrastructure supports only the x86, arm, arm64 and
+powerpc architectures.
 
 This infrastructure was ported from grsecurity [6] and PaX [7].
 
index fc73eeb7b3b8b119083a03a42e0046a564ea2f0e..ab02304613771b6f6e120da96fb677c293d032d2 100644 (file)
@@ -1006,7 +1006,8 @@ accept_redirects - BOOLEAN
                FALSE (router)
 
 forwarding - BOOLEAN
-       Enable IP forwarding on this interface.
+       Enable IP forwarding on this interface.  This controls whether packets
+       received _on_ this interface can be forwarded.
 
 mc_forwarding - BOOLEAN
        Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
index c776906f67a9f6795a0aef555a7fe348d07c506f..c45c02bc6082f322bdfefe8cccb52897e49eae4b 100644 (file)
@@ -3216,7 +3216,6 @@ F:        drivers/platform/chrome/
 
 CISCO VIC ETHERNET NIC DRIVER
 M:     Christian Benvenuti <benve@cisco.com>
-M:     Sujith Sankar <ssujith@cisco.com>
 M:     Govindarajulu Varadarajan <_govind@gmx.com>
 M:     Neel Patel <neepatel@cisco.com>
 S:     Supported
@@ -7774,13 +7773,6 @@ F:       include/net/mac80211.h
 F:     net/mac80211/
 F:     drivers/net/wireless/mac80211_hwsim.[ch]
 
-MACVLAN DRIVER
-M:     Patrick McHardy <kaber@trash.net>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/macvlan.c
-F:     include/linux/if_macvlan.h
-
 MAILBOX API
 M:     Jassi Brar <jassisinghbrar@gmail.com>
 L:     linux-kernel@vger.kernel.org
@@ -7853,6 +7845,8 @@ F:        drivers/net/ethernet/marvell/mvneta.*
 MARVELL MWIFIEX WIRELESS DRIVER
 M:     Amitkumar Karwar <akarwar@marvell.com>
 M:     Nishant Sarmukadam <nishants@marvell.com>
+M:     Ganapathi Bhat <gbhat@marvell.com>
+M:     Xinming Hu <huxm@marvell.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/marvell/mwifiex/
@@ -13383,14 +13377,6 @@ W:     https://linuxtv.org
 S:     Maintained
 F:     drivers/media/platform/vivid/*
 
-VLAN (802.1Q)
-M:     Patrick McHardy <kaber@trash.net>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/macvlan.c
-F:     include/linux/if_*vlan.h
-F:     net/8021q/
-
 VLYNQ BUS
 M:     Florian Fainelli <f.fainelli@gmail.com>
 L:     openwrt-devel@lists.openwrt.org (subscribers-only)
index b841fb36beb2b5aa594907a4a5efbb8333e77548..b2faa93193729f43ea80d5fe83f8adf41b220b78 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Fearless Coyote
 
 # *DOCUMENTATION*
index 02981eae96b99413f28ddb76cdcc90c810c5ae37..1ec8e0d801912fbb080b7f3ff880d017f60bf320 100644 (file)
                        label = "home";
                        linux,code = <KEY_HOME>;
                        gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                button@1 {
                        label = "menu";
                        linux,code = <KEY_MENU>;
                        gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
        };
index 0d341c545b010fb810b890166eae3aa7967313ea..e5ac1d81d15c9e482ab06b41830e5230a0187e69 100644 (file)
                        /* ID & VBUS GPIOs provided in board dts */
                };
        };
+
+       tpic2810: tpic2810@60 {
+               compatible = "ti,tpic2810";
+               reg = <0x60>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
 };
 
 &mcspi3 {
                spi-max-frequency = <1000000>;
                spi-cpol;
        };
-
-       tpic2810: tpic2810@60 {
-               compatible = "ti,tpic2810";
-               reg = <0x60>;
-               gpio-controller;
-               #gpio-cells = <2>;
-       };
 };
 
 &uart3 {
index 4fbb089cf5ad3c1f96a15f504ee433ff06b724df..00de62dc0042f1445851d1cb84c2cbea3e28d25f 100644 (file)
                timer@20200 {
                        compatible = "arm,cortex-a9-global-timer";
                        reg = <0x20200 0x100>;
-                       interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
                        clocks = <&periph_clk>;
                };
 
                local-timer@20600 {
                        compatible = "arm,cortex-a9-twd-timer";
                        reg = <0x20600 0x100>;
-                       interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_PPI 13 IRQ_TYPE_EDGE_RISING>;
                        clocks = <&periph_clk>;
                };
 
index bfd923096a8c1f5487b4bed2302ee8c784c395c7..ae31a5826e918ec58fc1948df0f9998664b7064f 100644 (file)
        };
 
        memory {
-               reg = <0x00000000 0x10000000>;
+               reg = <0x80000000 0x10000000>;
        };
 };
 
 &uart0 {
-       clock-frequency = <62499840>;
+       status = "okay";
 };
 
 &uart1 {
-       clock-frequency = <62499840>;
        status = "okay";
 };
index 3f04a40eb90cc904afb27fb71603270a8d8e1bea..df05e7f568af3e36bb2aa703d39fdbec37a6cece 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index 9fd542200d3d52229e1a0651330a5ef48b2ee8a9..4a3ab19c62819fb8c57d9ccf406100b64b15c598 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index 41e7fd350fcd1bbf6c36008c5f1e1c179679ffe0..81f78435d8c76cca38cb777d86e139c7d3751151 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 31 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index 477c4860db52236fa12a70aef2235c302f4a2a45..c88b8fefcb2f13e3c9bd98321948c8988d8e428d 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index c0a499d5ba447d5503d6655541461dddb9f35317..d503fa0dde310ff7597aeb7d3bfc757bcca32291 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index f7eb5854a224486adbe98a33da6a4ae59b17a90a..cc0363b843c1a0ae777efa40a6f2e25b34cf1f4c 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index 16666324fda8b5b901af538423ad302d13b9f98d..74e15a3cd9f8efb6a65238054824ba7e22df0bc2 100644 (file)
@@ -55,6 +55,7 @@
        gpio-restart {
                compatible = "gpio-restart";
                gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+               open-source;
                priority = <200>;
        };
 };
index 49f466fe0b1dc2eecdaca3e6638dd80a12029bcd..dcfc9759143375decd12bea87ad5e7547837f3bd 100644 (file)
        };
 };
 
-&cpu0 {
-       arm-supply = <&sw1a_reg>;
-       soc-supply = <&sw1c_reg>;
-};
-
 &fec1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet1>;
index 22332be7214032fd3ba710def036168f3f9c2b3c..528b4e9c6d3d30928d363ffc6cf1d8d2275a8ce7 100644 (file)
                };
 
                usb1: ohci@00400000 {
-                       compatible = "atmel,sama5d2-ohci", "usb-ohci";
+                       compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00400000 0x100000>;
                        interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>;
                        clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
index 82d8c477129359952b0ae499a2fdefca9393bdf4..162e1eb5373d3475fa785639223dd80750d5ca42 100644 (file)
@@ -14,6 +14,7 @@
 #include <dt-bindings/mfd/dbx500-prcmu.h>
 #include <dt-bindings/arm/ux500_pm_domains.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/ste-ab8500.h>
 #include "skeleton.dtsi"
 
 / {
                                interrupt-controller;
                                #interrupt-cells = <2>;
 
+                               ab8500_clock: clock-controller {
+                                       compatible = "stericsson,ab8500-clk";
+                                       #clock-cells = <1>;
+                               };
+
                                ab8500_gpio: ab8500-gpio {
                                        compatible = "stericsson,ab8500-gpio";
                                        gpio-controller;
 
                                ab8500-pwm {
                                        compatible = "stericsson,ab8500-pwm";
+                                       clocks = <&ab8500_clock AB8500_SYSCLK_INT>;
+                                       clock-names = "intclk";
                                };
 
                                ab8500-debugfs {
                                        V-AMIC2-supply = <&ab8500_ldo_anamic2_reg>;
                                        V-DMIC-supply = <&ab8500_ldo_dmic_reg>;
 
+                                       clocks = <&ab8500_clock AB8500_SYSCLK_AUDIO>;
+                                       clock-names = "audioclk";
+
                                        stericsson,earpeice-cmv = <950>; /* Units in mV. */
                                };
 
                        status = "disabled";
                };
 
+               sound {
+                       compatible = "stericsson,snd-soc-mop500";
+                       stericsson,cpu-dai = <&msp1 &msp3>;
+                       stericsson,audio-codec = <&codec>;
+                       clocks = <&prcmu_clk PRCMU_SYSCLK>, <&ab8500_clock AB8500_SYSCLK_ULP>, <&ab8500_clock AB8500_SYSCLK_INT>;
+                       clock-names = "sysclk", "ulpclk", "intclk";
+               };
+
                msp0: msp@80123000 {
                        compatible = "stericsson,ux500-msp-i2s";
                        reg = <0x80123000 0x1000>;
index f37f9e10713cc878ce9ee0393aa4b0c6ad239adf..9e359e4f342e76ebd1fbfab57d1f8f427ece2cd7 100644 (file)
                        status = "okay";
                };
 
-               sound {
-                       compatible = "stericsson,snd-soc-mop500";
-
-                       stericsson,cpu-dai = <&msp1 &msp3>;
-                       stericsson,audio-codec = <&codec>;
-                       clocks = <&prcmu_clk PRCMU_SYSCLK>;
-                       clock-names = "sysclk";
-               };
-
                msp0: msp@80123000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&msp0_default_mode>;
index dd5514def6042470aabea1ee29853d6c713c2691..ade1d0d4e5f45c595f079c251c8b93dbe95742df 100644 (file)
                                     "", "", "", "", "", "", "", "";
                };
 
-               sound {
-                       compatible = "stericsson,snd-soc-mop500";
-
-                       stericsson,cpu-dai = <&msp1 &msp3>;
-                       stericsson,audio-codec = <&codec>;
-                       clocks = <&prcmu_clk PRCMU_SYSCLK>;
-                       clock-names = "sysclk";
-               };
-
                msp0: msp@80123000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&msp0_default_mode>;
index 72ec0d5ae052cda33bc05a0086cd7e34a684184c..bbf1c8cbaac6aa19a6acd946a0230220e4e11417 100644 (file)
                                        reg = <8>;
                                        label = "cpu";
                                        ethernet = <&gmac>;
-                                       phy-mode = "rgmii";
+                                       phy-mode = "rgmii-txid";
                                        fixed-link {
                                                speed = <1000>;
                                                full-duplex;
index a952cc0703cc172b3a50ab334b1eec6b44a93df8..8a3ed21cb7bcfcf4785784bcb66d10aafd2081e7 100644 (file)
                        resets = <&ccu RST_BUS_GPU>;
 
                        assigned-clocks = <&ccu CLK_GPU>;
-                       assigned-clock-rates = <408000000>;
+                       assigned-clock-rates = <384000000>;
                };
 
                gic: interrupt-controller@01c81000 {
index 7097c18ff487d4851ca5d76d73e018b75aed7cb2..d6bd15898db6d6cc880fe0abb4999712450dc50e 100644 (file)
@@ -50,8 +50,6 @@
 
        backlight: backlight {
                compatible = "pwm-backlight";
-               pinctrl-names = "default";
-               pinctrl-0 = <&bl_en_pin>;
                pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
                brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
                default-brightness-level = <8>;
 };
 
 &pio {
-       bl_en_pin: bl_en_pin@0 {
-               pins = "PH6";
-               function = "gpio_in";
-       };
-
        mmc0_cd_pin: mmc0_cd_pin@0 {
                pins = "PB4";
                function = "gpio_in";
index f2462a6bdba6e7fcfc8c04815dd763bdcd5b3069..decd388d613d7e1d65c5d194f77fb23061ed37e0 100644 (file)
@@ -188,6 +188,7 @@ CONFIG_WL12XX=m
 CONFIG_WL18XX=m
 CONFIG_WLCORE_SPI=m
 CONFIG_WLCORE_SDIO=m
+CONFIG_INPUT_MOUSEDEV=m
 CONFIG_INPUT_JOYDEV=m
 CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_ATKBD=m
index 3d89b7905bd903687b481fccab7249382c2428c6..a277981f414d8dd9433569c529068f206daab81f 100644 (file)
@@ -289,6 +289,22 @@ static void at91_ddr_standby(void)
                at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
 }
 
+static void sama5d3_ddr_standby(void)
+{
+       u32 lpr0;
+       u32 saved_lpr0;
+
+       saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+       lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
+       lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN;
+
+       at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
+
+       cpu_do_idle();
+
+       at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
+}
+
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
  * remember.
  */
@@ -323,7 +339,7 @@ static const struct of_device_id const ramc_ids[] __initconst = {
        { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
        { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
        { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
-       { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
+       { .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby },
        { /*sentinel*/ }
 };
 
index 093458b62c8dadbcc3c7cc1c3b66d84e59af3d8d..c89757abb0ae4bc82adf923a5947f2c0fbefb42c 100644 (file)
@@ -241,6 +241,3 @@ obj-$(CONFIG_MACH_OMAP2_TUSB6010)   += usb-tusb6010.o
 
 onenand-$(CONFIG_MTD_ONENAND_OMAP2)    := gpmc-onenand.o
 obj-y                                  += $(onenand-m) $(onenand-y)
-
-nand-$(CONFIG_MTD_NAND_OMAP2)          := gpmc-nand.o
-obj-y                                  += $(nand-m) $(nand-y)
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
deleted file mode 100644 (file)
index f6ac027..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * gpmc-nand.c
- *
- * Copyright (C) 2009 Texas Instruments
- * Vimal Singh <vimalsingh@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/omap-gpmc.h>
-#include <linux/mtd/nand.h>
-#include <linux/platform_data/mtd-nand-omap2.h>
-
-#include <asm/mach/flash.h>
-
-#include "soc.h"
-
-/* minimum size for IO mapping */
-#define        NAND_IO_SIZE    4
-
-static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
-{
-       /* platforms which support all ECC schemes */
-       if (soc_is_am33xx() || soc_is_am43xx() || cpu_is_omap44xx() ||
-                soc_is_omap54xx() || soc_is_dra7xx())
-               return 1;
-
-       if (ecc_opt == OMAP_ECC_BCH4_CODE_HW_DETECTION_SW ||
-                ecc_opt == OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) {
-               if (cpu_is_omap24xx())
-                       return 0;
-               else if (cpu_is_omap3630() && (GET_OMAP_REVISION() == 0))
-                       return 0;
-               else
-                       return 1;
-       }
-
-       /* OMAP3xxx do not have ELM engine, so cannot support ECC schemes
-        * which require H/W based ECC error detection */
-       if ((cpu_is_omap34xx() || cpu_is_omap3630()) &&
-           ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
-                (ecc_opt == OMAP_ECC_BCH8_CODE_HW)))
-               return 0;
-
-       /* legacy platforms support only HAM1 (1-bit Hamming) ECC scheme */
-       if (ecc_opt == OMAP_ECC_HAM1_CODE_HW ||
-           ecc_opt == OMAP_ECC_HAM1_CODE_SW)
-               return 1;
-       else
-               return 0;
-}
-
-/* This function will go away once the device-tree convertion is complete */
-static void gpmc_set_legacy(struct omap_nand_platform_data *gpmc_nand_data,
-                           struct gpmc_settings *s)
-{
-       /* Enable RD PIN Monitoring Reg */
-       if (gpmc_nand_data->dev_ready) {
-               s->wait_on_read = true;
-               s->wait_on_write = true;
-       }
-
-       if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-               s->device_width = GPMC_DEVWIDTH_16BIT;
-       else
-               s->device_width = GPMC_DEVWIDTH_8BIT;
-}
-
-int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
-                  struct gpmc_timings *gpmc_t)
-{
-       int err = 0;
-       struct gpmc_settings s;
-       struct platform_device *pdev;
-       struct resource gpmc_nand_res[] = {
-               { .flags = IORESOURCE_MEM, },
-               { .flags = IORESOURCE_IRQ, },
-               { .flags = IORESOURCE_IRQ, },
-       };
-
-       BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM);
-
-       err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-                             (unsigned long *)&gpmc_nand_res[0].start);
-       if (err < 0) {
-               pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n",
-                      gpmc_nand_data->cs, err);
-               return err;
-       }
-       gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
-       gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
-       gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
-
-       memset(&s, 0, sizeof(struct gpmc_settings));
-       gpmc_set_legacy(gpmc_nand_data, &s);
-
-       s.device_nand = true;
-
-       if (gpmc_t) {
-               err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t, &s);
-               if (err < 0) {
-                       pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n",
-                              err);
-                       return err;
-               }
-       }
-
-       err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
-       if (err < 0)
-               goto out_free_cs;
-
-       err = gpmc_configure(GPMC_CONFIG_WP, 0);
-       if (err < 0)
-               goto out_free_cs;
-
-       if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
-               pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
-               err = -EINVAL;
-               goto out_free_cs;
-       }
-
-
-       pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
-       if (pdev) {
-               err = platform_device_add_resources(pdev, gpmc_nand_res,
-                                                   ARRAY_SIZE(gpmc_nand_res));
-               if (!err)
-                       pdev->dev.platform_data = gpmc_nand_data;
-       } else {
-               err = -ENOMEM;
-       }
-       if (err)
-               goto out_free_pdev;
-
-       err = platform_device_add(pdev);
-       if (err) {
-               dev_err(&pdev->dev, "Unable to register NAND device\n");
-               goto out_free_pdev;
-       }
-
-       return 0;
-
-out_free_pdev:
-       platform_device_put(pdev);
-out_free_cs:
-       gpmc_cs_free(gpmc_nand_data->cs);
-
-       return err;
-}
index 8633c703546a65c2e5b0071ffca0d5a12b664884..2944af82055847935462da4035a73b513c5795a6 100644 (file)
@@ -367,7 +367,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
        return ret;
 }
 
-void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+int gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
        int err;
        struct device *dev = &gpmc_onenand_device.dev;
@@ -393,15 +393,17 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
        if (err < 0) {
                dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
                        gpmc_onenand_data->cs, err);
-               return;
+               return err;
        }
 
        gpmc_onenand_resource.end = gpmc_onenand_resource.start +
                                                        ONENAND_IO_SIZE - 1;
 
-       if (platform_device_register(&gpmc_onenand_device) < 0) {
+       err = platform_device_register(&gpmc_onenand_device);
+       if (err) {
                dev_err(dev, "Unable to register OneNAND device\n");
                gpmc_cs_free(gpmc_onenand_data->cs);
-               return;
        }
+
+       return err;
 }
index fe36ce2734d47a81f8dd5cbfdf72e9f6717df903..4c6f14cf92a82e3dbf8d7ceeb985686feb79e924 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 
 #include "omap44xx.h"
 
@@ -66,7 +67,7 @@ wait_2:       ldr     r2, =AUX_CORE_BOOT0_PA  @ read from AuxCoreBoot0
        cmp     r0, r4
        bne     wait_2
        ldr     r12, =API_HYP_ENTRY
-       adr     r0, hyp_boot
+       badr    r0, hyp_boot
        smc     #0
 hyp_boot:
        b       omap_secondary_startup
index 56f917ec8621e8d5d4a9410975ec454aa802414a..1435fee39a89ba18239291859c97f0f333ca877f 100644 (file)
@@ -2112,11 +2112,20 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
 };
 
 /* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
+       {
+               .pa_start       = OMAP34XX_SR1_BASE,
+               .pa_end         = OMAP34XX_SR1_BASE + SZ_1K - 1,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { },
+};
 
 static struct omap_hwmod_ocp_if omap34xx_l4_core__sr1 = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap34xx_sr1_hwmod,
        .clk            = "sr_l4_ick",
+       .addr           = omap3_sr1_addr_space,
        .user           = OCP_USER_MPU,
 };
 
@@ -2124,15 +2133,25 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr1 = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap36xx_sr1_hwmod,
        .clk            = "sr_l4_ick",
+       .addr           = omap3_sr1_addr_space,
        .user           = OCP_USER_MPU,
 };
 
 /* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
+       {
+               .pa_start       = OMAP34XX_SR2_BASE,
+               .pa_end         = OMAP34XX_SR2_BASE + SZ_1K - 1,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { },
+};
 
 static struct omap_hwmod_ocp_if omap34xx_l4_core__sr2 = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap34xx_sr2_hwmod,
        .clk            = "sr_l4_ick",
+       .addr           = omap3_sr2_addr_space,
        .user           = OCP_USER_MPU,
 };
 
@@ -2140,6 +2159,7 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr2 = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap36xx_sr2_hwmod,
        .clk            = "sr_l4_ick",
+       .addr           = omap3_sr2_addr_space,
        .user           = OCP_USER_MPU,
 };
 
@@ -3111,16 +3131,20 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_hwmod_ocp_ifs[] __initdata = {
  * Return: 0 if device named @dev_name is not likely to be accessible,
  * or 1 if it is likely to be accessible.
  */
-static int __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus,
-                                                      const char *dev_name)
+static bool __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus,
+                                                       const char *dev_name)
 {
+       struct device_node *node;
+       bool available;
+
        if (!bus)
-               return (omap_type() == OMAP2_DEVICE_TYPE_GP) ? 1 : 0;
+               return omap_type() == OMAP2_DEVICE_TYPE_GP;
 
-       if (of_device_is_available(of_find_node_by_name(bus, dev_name)))
-               return 1;
+       node = of_get_child_by_name(bus, dev_name);
+       available = of_device_is_available(node);
+       of_node_put(node);
 
-       return 0;
+       return available;
 }
 
 int __init omap3xxx_hwmod_init(void)
@@ -3189,15 +3213,20 @@ int __init omap3xxx_hwmod_init(void)
 
        if (h_sham && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "sham")) {
                r = omap_hwmod_register_links(h_sham);
-               if (r < 0)
+               if (r < 0) {
+                       of_node_put(bus);
                        return r;
+               }
        }
 
        if (h_aes && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "aes")) {
                r = omap_hwmod_register_links(h_aes);
-               if (r < 0)
+               if (r < 0) {
+                       of_node_put(bus);
                        return r;
+               }
        }
+       of_node_put(bus);
 
        /*
         * Register hwmod links specific to certain ES levels of a
index 3c2cb5d5adfa4f17bab53005b7722ffe8add022e..0bb0e9c6376c4aab7bb1ad43c2bd4fce87cef943 100644 (file)
 394    common  pkey_mprotect           sys_pkey_mprotect
 395    common  pkey_alloc              sys_pkey_alloc
 396    common  pkey_free               sys_pkey_free
+397    common  statx                   sys_statx
index 8c7c244247b6b3f6d0a52a4417a802873f53bde0..3741859765cfe050d2c4a174d613ff90e1074be0 100644 (file)
@@ -1073,6 +1073,10 @@ config SYSVIPC_COMPAT
        def_bool y
        depends on COMPAT && SYSVIPC
 
+config KEYS_COMPAT
+       def_bool y
+       depends on COMPAT && KEYS
+
 endmenu
 
 menu "Power management options"
index 9f9e203c09c5ad362ae00d5038d2e52c91043f39..bcb03fc3266552e22ce855ac81677584d0937e63 100644 (file)
        pcie0: pcie@20020000 {
                compatible = "brcm,iproc-pcie";
                reg = <0 0x20020000 0 0x1000>;
+               dma-coherent;
 
                #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 0 0>;
        pcie4: pcie@50020000 {
                compatible = "brcm,iproc-pcie";
                reg = <0 0x50020000 0 0x1000>;
+               dma-coherent;
 
                #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 0 0>;
        pcie8: pcie@60c00000 {
                compatible = "brcm,iproc-pcie-paxc";
                reg = <0 0x60c00000 0 0x1000>;
+               dma-coherent;
                linux,pci-domain = <8>;
 
                bus-range = <0x0 0x1>;
                              <0x61030000 0x100>;
                        reg-names = "amac_base", "idm_base", "nicpm_base";
                        interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-coherent;
                        phy-handle = <&gphy0>;
                        phy-mode = "rgmii";
                        status = "disabled";
                        reg = <0x612c0000 0x445>;  /* PDC FS0 regs */
                        interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
                        #mbox-cells = <1>;
+                       dma-coherent;
                        brcm,rx-status-len = <32>;
                        brcm,use-bcm-hdr;
                };
                        reg = <0x612e0000 0x445>;  /* PDC FS1 regs */
                        interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
                        #mbox-cells = <1>;
+                       dma-coherent;
                        brcm,rx-status-len = <32>;
                        brcm,use-bcm-hdr;
                };
                        reg = <0x61300000 0x445>;  /* PDC FS2 regs */
                        interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
                        #mbox-cells = <1>;
+                       dma-coherent;
                        brcm,rx-status-len = <32>;
                        brcm,use-bcm-hdr;
                };
                        reg = <0x61320000 0x445>;  /* PDC FS3 regs */
                        interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
                        #mbox-cells = <1>;
+                       dma-coherent;
                        brcm,rx-status-len = <32>;
                        brcm,use-bcm-hdr;
                };
                sata: ahci@663f2000 {
                        compatible = "brcm,iproc-ahci", "generic-ahci";
                        reg = <0x663f2000 0x1000>;
+                       dma-coherent;
                        reg-names = "ahci";
                        interrupts = <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>;
                        #address-cells = <1>;
                        compatible = "brcm,sdhci-iproc-cygnus";
                        reg = <0x66420000 0x100>;
                        interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-coherent;
                        bus-width = <8>;
                        clocks = <&genpll_sw BCM_NS2_GENPLL_SW_SDIO_CLK>;
                        status = "disabled";
                        compatible = "brcm,sdhci-iproc-cygnus";
                        reg = <0x66430000 0x100>;
                        interrupts = <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-coherent;
                        bus-width = <8>;
                        clocks = <&genpll_sw BCM_NS2_GENPLL_SW_SDIO_CLK>;
                        status = "disabled";
index 05310ad8c5abec54a445cb2dfcd3df5fefcefe3a..f31c48d0cd6873f399a6d8f5f861e98fa3f66e10 100644 (file)
@@ -251,7 +251,7 @@ static inline bool system_supports_fpsimd(void)
 static inline bool system_uses_ttbr0_pan(void)
 {
        return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
-               !cpus_have_cap(ARM64_HAS_PAN);
+               !cpus_have_const_cap(ARM64_HAS_PAN);
 }
 
 #endif /* __ASSEMBLY__ */
index e78ac26324bd809dcd5fa2f7f45465daba8c158d..bdbeb06dc11ede112de28b09c7608b3d5b0ce23b 100644 (file)
@@ -44,7 +44,7 @@
 #define __ARM_NR_compat_cacheflush     (__ARM_NR_COMPAT_BASE+2)
 #define __ARM_NR_compat_set_tls                (__ARM_NR_COMPAT_BASE+5)
 
-#define __NR_compat_syscalls           394
+#define __NR_compat_syscalls           398
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
index b7e8ef16ff0dc62b94a042e4a0b70c9884e4cb16..c66b51aab1958816e6d137e9ae9dc0dc0378cf7f 100644 (file)
@@ -809,6 +809,14 @@ __SYSCALL(__NR_copy_file_range, sys_copy_file_range)
 __SYSCALL(__NR_preadv2, compat_sys_preadv2)
 #define __NR_pwritev2 393
 __SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
+#define __NR_pkey_mprotect 394
+__SYSCALL(__NR_pkey_mprotect, sys_pkey_mprotect)
+#define __NR_pkey_alloc 395
+__SYSCALL(__NR_pkey_alloc, sys_pkey_alloc)
+#define __NR_pkey_free 396
+__SYSCALL(__NR_pkey_free, sys_pkey_free)
+#define __NR_statx 397
+__SYSCALL(__NR_statx, sys_statx)
 
 /*
  * Please add new compat syscalls above this comment and update
index 75a0f8acef669ce5560f627f516dae54168a898d..fd691087dc9ad58ff0ff007f5ea7191a3f879380 100644 (file)
@@ -30,7 +30,7 @@ int arm_cpuidle_init(unsigned int cpu)
 }
 
 /**
- * cpu_suspend() - function to enter a low-power idle state
+ * arm_cpuidle_suspend() - function to enter a low-power idle state
  * @arg: argument to pass to CPU suspend operations
  *
  * Return: 0 on success, -EOPNOTSUPP if CPU suspend hook not initialized, CPU
index 769f24ef628c1e9ffd167e0b0e634151cf36de3d..d7e90d97f5c405f2c348eaaff331df818b27906a 100644 (file)
@@ -131,11 +131,15 @@ u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset)
        /*
         * The kernel Image should not extend across a 1GB/32MB/512MB alignment
         * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this
-        * happens, increase the KASLR offset by the size of the kernel image.
+        * happens, increase the KASLR offset by the size of the kernel image
+        * rounded up by SWAPPER_BLOCK_SIZE.
         */
        if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) !=
-           (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT))
-               offset = (offset + (u64)(_end - _text)) & mask;
+           (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT)) {
+               u64 kimg_sz = _end - _text;
+               offset = (offset + round_up(kimg_sz, SWAPPER_BLOCK_SIZE))
+                               & mask;
+       }
 
        if (IS_ENABLED(CONFIG_KASAN))
                /*
index 2a07aae5b8a26431edcdfd2534a856474fc00b44..c5c45942fb6e6693c5f8c195bb6596e2fa9f6ff2 100644 (file)
@@ -372,12 +372,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
        return 0;
 }
 
-int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
-                                      unsigned long val, void *data)
-{
-       return NOTIFY_DONE;
-}
-
 static void __kprobes kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *p, *cur_kprobe;
index 55d1e9205543689a6883d983dc82cb8b9eb2be6a..687a358a37337af9cf7a0d50c27b0176cfbd2012 100644 (file)
@@ -162,7 +162,7 @@ void __init kasan_init(void)
        clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
        vmemmap_populate(kimg_shadow_start, kimg_shadow_end,
-                        pfn_to_nid(virt_to_pfn(_text)));
+                        pfn_to_nid(virt_to_pfn(lm_alias(_text))));
 
        /*
         * vmemmap_populate() has populated the shadow region that covers the
index 5fcb9ac72693850f50060a4822445a09d81b8a80..f0a5d8b844d6b85b16eb6c170f8af86f73ad8440 100644 (file)
@@ -77,7 +77,11 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
        return val;
 }
 
-#define xchg(ptr, with) \
-       ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), sizeof(*(ptr))))
+#define xchg(ptr, with)                                                \
+       ({                                                              \
+               (__typeof__(*(ptr))) __xchg((unsigned long)(with),      \
+                                           (ptr),                      \
+                                           sizeof(*(ptr)));            \
+       })
 
 #endif /* __ASM_OPENRISC_CMPXCHG_H */
index 140faa16685a2325f3a1b6cbf9cbb9c8e68fc913..1311e6b139916692bb5f81fbfd188a48b844d977 100644 (file)
@@ -211,7 +211,7 @@ do {                                                                        \
        case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break;         \
        case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break;         \
        case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break;         \
-       case 8: __get_user_asm2(x, ptr, retval);                        \
+       case 8: __get_user_asm2(x, ptr, retval); break;                 \
        default: (x) = __get_user_bad();                                \
        }                                                               \
 } while (0)
index 5c4695d13542fc003054995b728ac468e18bd94c..ee3e604959e15c514bc91eb65118d8d04ea20b59 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/pgalloc.h>
+#include <asm/pgtable.h>
 
 #define DECLARE_EXPORT(name) extern void name(void); EXPORT_SYMBOL(name)
 
@@ -42,6 +43,9 @@ DECLARE_EXPORT(__muldi3);
 DECLARE_EXPORT(__ashrdi3);
 DECLARE_EXPORT(__ashldi3);
 DECLARE_EXPORT(__lshrdi3);
+DECLARE_EXPORT(__ucmpdi2);
 
+EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(__copy_tofrom_user);
+EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(memset);
index 828a29110459e8cb9f1e85b1b5033f30ef0348dd..f8da545854f979c33a7b3116d26d822caa46c494 100644 (file)
@@ -90,6 +90,7 @@ void arch_cpu_idle(void)
 }
 
 void (*pm_power_off) (void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
 
 /*
  * When a process does an "exec", machine state like FPU and debug
index 19c9c3c5f267eac813edf6c5fc6f358301d2a639..c7e15cc5c6683b423d028b1557fc0dc9b7dd5a16 100644 (file)
@@ -43,28 +43,9 @@ static inline void flush_kernel_dcache_page(struct page *page)
 
 #define flush_kernel_dcache_range(start,size) \
        flush_kernel_dcache_range_asm((start), (start)+(size));
-/* vmap range flushes and invalidates.  Architecturally, we don't need
- * the invalidate, because the CPU should refuse to speculate once an
- * area has been flushed, so invalidate is left empty */
-static inline void flush_kernel_vmap_range(void *vaddr, int size)
-{
-       unsigned long start = (unsigned long)vaddr;
-
-       flush_kernel_dcache_range_asm(start, start + size);
-}
-static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
-{
-       unsigned long start = (unsigned long)vaddr;
-       void *cursor = vaddr;
 
-       for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) {
-               struct page *page = vmalloc_to_page(cursor);
-
-               if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
-                       flush_kernel_dcache_page(page);
-       }
-       flush_kernel_dcache_range_asm(start, start + size);
-}
+void flush_kernel_vmap_range(void *vaddr, int size);
+void invalidate_kernel_vmap_range(void *vaddr, int size);
 
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
index fb4382c28259b3ff2f873014fce7e42f1373dac8..edfbf9d6a6dd76adae077d49d76a236d299bceda 100644 (file)
@@ -32,7 +32,8 @@
  * that put_user is the same as __put_user, etc.
  */
 
-#define access_ok(type, uaddr, size) (1)
+#define access_ok(type, uaddr, size)   \
+       ( (uaddr) == (uaddr) )
 
 #define put_user __put_user
 #define get_user __get_user
index 6b0741e7a7ed3ee4060d619a8999b50dab12dac3..667c99421003e4dd07c6d204bef7db08fa905933 100644 (file)
 #define __NR_copy_file_range   (__NR_Linux + 346)
 #define __NR_preadv2           (__NR_Linux + 347)
 #define __NR_pwritev2          (__NR_Linux + 348)
+#define __NR_statx             (__NR_Linux + 349)
 
-#define __NR_Linux_syscalls    (__NR_pwritev2 + 1)
+#define __NR_Linux_syscalls    (__NR_statx + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 0dc72d5de861539e5c16ff2ecd49f205e37775e6..c32a0909521665b5f08c22ef37fa8d8f9c654012 100644 (file)
@@ -616,3 +616,25 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
                __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
        }
 }
+
+void flush_kernel_vmap_range(void *vaddr, int size)
+{
+       unsigned long start = (unsigned long)vaddr;
+
+       if ((unsigned long)size > parisc_cache_flush_threshold)
+               flush_data_cache();
+       else
+               flush_kernel_dcache_range_asm(start, start + size);
+}
+EXPORT_SYMBOL(flush_kernel_vmap_range);
+
+void invalidate_kernel_vmap_range(void *vaddr, int size)
+{
+       unsigned long start = (unsigned long)vaddr;
+
+       if ((unsigned long)size > parisc_cache_flush_threshold)
+               flush_data_cache();
+       else
+               flush_kernel_dcache_range_asm(start, start + size);
+}
+EXPORT_SYMBOL(invalidate_kernel_vmap_range);
index a0ecdb4abcc878b3805d7a2d0f845272b1fc372d..c66c943d93224f342cb71c97bd6a690bf8fb225b 100644 (file)
@@ -620,6 +620,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                         */
                        *loc = fsel(val, addend); 
                        break;
+               case R_PARISC_SECREL32:
+                       /* 32-bit section relative address. */
+                       *loc = fsel(val, addend);
+                       break;
                case R_PARISC_DPREL21L:
                        /* left 21 bit of relative address */
                        val = lrsel(val - dp, addend);
@@ -807,6 +811,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                         */
                        *loc = fsel(val, addend); 
                        break;
+               case R_PARISC_SECREL32:
+                       /* 32-bit section relative address. */
+                       *loc = fsel(val, addend);
+                       break;
                case R_PARISC_FPTR64:
                        /* 64-bit function address */
                        if(in_local(me, (void *)(val + addend))) {
index e282a5131d77e10f62d274d4be426b076f655017..6017a5af2e6e2c8feb45de54adfb36865b65d3ee 100644 (file)
@@ -39,7 +39,7 @@
  *  the PDC INTRIGUE calls.  This is done to eliminate bugs introduced
  *  in various PDC revisions.  The code is much more maintainable
  *  and reliable this way vs having to debug on every version of PDC
- *  on every box. 
+ *  on every box.
  */
 
 #include <linux/capability.h>
@@ -195,8 +195,8 @@ static int perf_config(uint32_t *image_ptr);
 static int perf_release(struct inode *inode, struct file *file);
 static int perf_open(struct inode *inode, struct file *file);
 static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos);
-static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, 
-       loff_t *ppos);
+static ssize_t perf_write(struct file *file, const char __user *buf,
+       size_t count, loff_t *ppos);
 static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static void perf_start_counters(void);
 static int perf_stop_counters(uint32_t *raddr);
@@ -222,7 +222,7 @@ extern void perf_intrigue_disable_perf_counters (void);
 /*
  * configure:
  *
- * Configure the cpu with a given data image.  First turn off the counters, 
+ * Configure the cpu with a given data image.  First turn off the counters,
  * then download the image, then turn the counters back on.
  */
 static int perf_config(uint32_t *image_ptr)
@@ -234,7 +234,7 @@ static int perf_config(uint32_t *image_ptr)
        error = perf_stop_counters(raddr);
        if (error != 0) {
                printk("perf_config: perf_stop_counters = %ld\n", error);
-               return -EINVAL; 
+               return -EINVAL;
        }
 
 printk("Preparing to write image\n");
@@ -242,7 +242,7 @@ printk("Preparing to write image\n");
        error = perf_write_image((uint64_t *)image_ptr);
        if (error != 0) {
                printk("perf_config: DOWNLOAD = %ld\n", error);
-               return -EINVAL; 
+               return -EINVAL;
        }
 
 printk("Preparing to start counters\n");
@@ -254,7 +254,7 @@ printk("Preparing to start counters\n");
 }
 
 /*
- * Open the device and initialize all of its memory.  The device is only 
+ * Open the device and initialize all of its memory.  The device is only
  * opened once, but can be "queried" by multiple processes that know its
  * file descriptor.
  */
@@ -298,19 +298,19 @@ static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t
  * called on the processor that the download should happen
  * on.
  */
-static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, 
-       loff_t *ppos)
+static ssize_t perf_write(struct file *file, const char __user *buf,
+       size_t count, loff_t *ppos)
 {
        size_t image_size;
        uint32_t image_type;
        uint32_t interface_type;
        uint32_t test;
 
-       if (perf_processor_interface == ONYX_INTF) 
+       if (perf_processor_interface == ONYX_INTF)
                image_size = PCXU_IMAGE_SIZE;
-       else if (perf_processor_interface == CUDA_INTF) 
+       else if (perf_processor_interface == CUDA_INTF)
                image_size = PCXW_IMAGE_SIZE;
-       else 
+       else
                return -EFAULT;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -330,22 +330,22 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun
 
        /* First check the machine type is correct for
           the requested image */
-        if (((perf_processor_interface == CUDA_INTF) &&
-                      (interface_type != CUDA_INTF)) ||
-           ((perf_processor_interface == ONYX_INTF) &&
-                      (interface_type != ONYX_INTF))) 
+       if (((perf_processor_interface == CUDA_INTF) &&
+                       (interface_type != CUDA_INTF)) ||
+               ((perf_processor_interface == ONYX_INTF) &&
+                       (interface_type != ONYX_INTF)))
                return -EINVAL;
 
        /* Next check to make sure the requested image
           is valid */
-       if (((interface_type == CUDA_INTF) && 
+       if (((interface_type == CUDA_INTF) &&
                       (test >= MAX_CUDA_IMAGES)) ||
-           ((interface_type == ONYX_INTF) && 
-                      (test >= MAX_ONYX_IMAGES))) 
+           ((interface_type == ONYX_INTF) &&
+                      (test >= MAX_ONYX_IMAGES)))
                return -EINVAL;
 
        /* Copy the image into the processor */
-       if (interface_type == CUDA_INTF) 
+       if (interface_type == CUDA_INTF)
                return perf_config(cuda_images[test]);
        else
                return perf_config(onyx_images[test]);
@@ -359,7 +359,7 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun
 static void perf_patch_images(void)
 {
 #if 0 /* FIXME!! */
-/* 
+/*
  * NOTE:  this routine is VERY specific to the current TLB image.
  * If the image is changed, this routine might also need to be changed.
  */
@@ -367,9 +367,9 @@ static void perf_patch_images(void)
        extern void $i_dtlb_miss_2_0();
        extern void PA2_0_iva();
 
-       /* 
+       /*
         * We can only use the lower 32-bits, the upper 32-bits should be 0
-        * anyway given this is in the kernel 
+        * anyway given this is in the kernel
         */
        uint32_t itlb_addr  = (uint32_t)&($i_itlb_miss_2_0);
        uint32_t dtlb_addr  = (uint32_t)&($i_dtlb_miss_2_0);
@@ -377,21 +377,21 @@ static void perf_patch_images(void)
 
        if (perf_processor_interface == ONYX_INTF) {
                /* clear last 2 bytes */
-               onyx_images[TLBMISS][15] &= 0xffffff00;  
+               onyx_images[TLBMISS][15] &= 0xffffff00;
                /* set 2 bytes */
                onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
                onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00;
                onyx_images[TLBMISS][17] = itlb_addr;
 
                /* clear last 2 bytes */
-               onyx_images[TLBHANDMISS][15] &= 0xffffff00;  
+               onyx_images[TLBHANDMISS][15] &= 0xffffff00;
                /* set 2 bytes */
                onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
                onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00;
                onyx_images[TLBHANDMISS][17] = itlb_addr;
 
                /* clear last 2 bytes */
-               onyx_images[BIG_CPI][15] &= 0xffffff00;  
+               onyx_images[BIG_CPI][15] &= 0xffffff00;
                /* set 2 bytes */
                onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24));
                onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00;
@@ -404,24 +404,24 @@ static void perf_patch_images(void)
 
        } else if (perf_processor_interface == CUDA_INTF) {
                /* Cuda interface */
-               cuda_images[TLBMISS][16] =  
+               cuda_images[TLBMISS][16] =
                        (cuda_images[TLBMISS][16]&0xffff0000) |
                        ((dtlb_addr >> 8)&0x0000ffff);
-               cuda_images[TLBMISS][17] = 
+               cuda_images[TLBMISS][17] =
                        ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
                cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000;
 
-               cuda_images[TLBHANDMISS][16] = 
+               cuda_images[TLBHANDMISS][16] =
                        (cuda_images[TLBHANDMISS][16]&0xffff0000) |
                        ((dtlb_addr >> 8)&0x0000ffff);
-               cuda_images[TLBHANDMISS][17] = 
+               cuda_images[TLBHANDMISS][17] =
                        ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
                cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000;
 
-               cuda_images[BIG_CPI][16] = 
+               cuda_images[BIG_CPI][16] =
                        (cuda_images[BIG_CPI][16]&0xffff0000) |
                        ((dtlb_addr >> 8)&0x0000ffff);
-               cuda_images[BIG_CPI][17] = 
+               cuda_images[BIG_CPI][17] =
                        ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
                cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000;
        } else {
@@ -433,7 +433,7 @@ static void perf_patch_images(void)
 
 /*
  * ioctl routine
- * All routines effect the processor that they are executed on.  Thus you 
+ * All routines effect the processor that they are executed on.  Thus you
  * must be running on the processor that you wish to change.
  */
 
@@ -459,7 +459,7 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        }
 
                        /* copy out the Counters */
-                       if (copy_to_user((void __user *)arg, raddr, 
+                       if (copy_to_user((void __user *)arg, raddr,
                                        sizeof (raddr)) != 0) {
                                error =  -EFAULT;
                                break;
@@ -487,7 +487,7 @@ static const struct file_operations perf_fops = {
        .open = perf_open,
        .release = perf_release
 };
-       
+
 static struct miscdevice perf_dev = {
        MISC_DYNAMIC_MINOR,
        PA_PERF_DEV,
@@ -595,7 +595,7 @@ static int perf_stop_counters(uint32_t *raddr)
                /* OR sticky2 (bit 1496) to counter2 bit 32 */
                tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
                raddr[2] = (uint32_t)tmp64;
-               
+
                /* Counter3 is bits 1497 to 1528 */
                tmp64 =  (userbuf[23] >> 7) & 0x00000000ffffffff;
                /* OR sticky3 (bit 1529) to counter3 bit 32 */
@@ -617,7 +617,7 @@ static int perf_stop_counters(uint32_t *raddr)
                userbuf[22] = 0;
                userbuf[23] = 0;
 
-               /* 
+               /*
                 * Write back the zeroed bytes + the image given
                 * the read was destructive.
                 */
@@ -625,13 +625,13 @@ static int perf_stop_counters(uint32_t *raddr)
        } else {
 
                /*
-                * Read RDR-15 which contains the counters and sticky bits 
+                * Read RDR-15 which contains the counters and sticky bits
                 */
                if (!perf_rdr_read_ubuf(15, userbuf)) {
                        return -13;
                }
 
-               /* 
+               /*
                 * Clear out the counters
                 */
                perf_rdr_clear(15);
@@ -644,7 +644,7 @@ static int perf_stop_counters(uint32_t *raddr)
                raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL);
                raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL);
        }
+
        return 0;
 }
 
@@ -682,7 +682,7 @@ static int perf_rdr_read_ubuf(uint32_t      rdr_num, uint64_t *buffer)
        i = tentry->num_words;
        while (i--) {
                buffer[i] = 0;
-       }       
+       }
 
        /* Check for bits an even number of 64 */
        if ((xbits = width & 0x03f) != 0) {
@@ -808,18 +808,22 @@ static int perf_write_image(uint64_t *memaddr)
        }
 
        runway = ioremap_nocache(cpu_device->hpa.start, 4096);
+       if (!runway) {
+               pr_err("perf_write_image: ioremap failed!\n");
+               return -ENOMEM;
+       }
 
        /* Merge intrigue bits into Runway STATUS 0 */
        tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful;
-       __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), 
+       __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul),
                     runway + RUNWAY_STATUS);
-       
+
        /* Write RUNWAY DEBUG registers */
        for (i = 0; i < 8; i++) {
                __raw_writeq(*memaddr++, runway + RUNWAY_DEBUG);
        }
 
-       return 0; 
+       return 0;
 }
 
 /*
@@ -843,7 +847,7 @@ printk("perf_rdr_write\n");
                        perf_rdr_shift_out_U(rdr_num, buffer[i]);
                } else {
                        perf_rdr_shift_out_W(rdr_num, buffer[i]);
-               }       
+               }
        }
 printk("perf_rdr_write done\n");
 }
index 06f7ca7fe70b616b4d68353ae10dd5d409bbbcab..b76f503eee4a83c14d7f8156f339952e521a26ed 100644 (file)
@@ -142,6 +142,8 @@ void machine_power_off(void)
 
        printk(KERN_EMERG "System shut down completed.\n"
               "Please power this system off now.");
+
+       for (;;);
 }
 
 void (*pm_power_off)(void) = machine_power_off;
index 3cfef1de8061af183820e98ca97467d674a8c463..44aeaa9c039fc421421a5b1b7524495e0d225eba 100644 (file)
        ENTRY_SAME(copy_file_range)
        ENTRY_COMP(preadv2)
        ENTRY_COMP(pwritev2)
+       ENTRY_SAME(statx)
 
 
 .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
index 861e72109df2da0b54c98a94584b8b4ff853026b..f080abfc2f83fbd1e7d63846904a3a21ad820cee 100644 (file)
@@ -68,6 +68,7 @@ SECTIONS
   }
 
 #ifdef CONFIG_PPC64_BOOT_WRAPPER
+  . = ALIGN(256);
   .got :
   {
     __toc_start = .;
index 9fa046d56ebadd6ad25e62b5a29a853b123cd30a..411994551afc138b0b733fdda2b6398140f7127c 100644 (file)
@@ -52,7 +52,7 @@ static int crc32c_vpmsum_cra_init(struct crypto_tfm *tfm)
 {
        u32 *key = crypto_tfm_ctx(tfm);
 
-       *key = 0;
+       *key = ~0;
 
        return 0;
 }
index 73eb794d6163811c45729984f0d9fb06bbde31a9..bc5fdfd227886aa2cb359656faf2eef5eb6574b7 100644 (file)
 #define PPC_BIT(bit)           (1UL << PPC_BITLSHIFT(bit))
 #define PPC_BITMASK(bs, be)    ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
 
+/* Put a PPC bit into a "normal" bit position */
+#define PPC_BITEXTRACT(bits, ppc_bit, dst_bit)                 \
+       ((((bits) >> PPC_BITLSHIFT(ppc_bit)) & 1) << (dst_bit))
+
 #include <asm/barrier.h>
 
 /* Macro for generating the ***_bits() functions */
index f97d8cb6bdf64fd8e147035d659b71016c33ecd0..ed62efe01e49ed1a2e37c6bbd6efbf41fed3e925 100644 (file)
 
 #define P8_DSISR_MC_SLB_ERRORS         (P7_DSISR_MC_SLB_ERRORS | \
                                         P8_DSISR_MC_ERAT_MULTIHIT_SEC)
+
+/*
+ * Machine Check bits on power9
+ */
+#define P9_SRR1_MC_LOADSTORE(srr1)     (((srr1) >> PPC_BITLSHIFT(42)) & 1)
+
+#define P9_SRR1_MC_IFETCH(srr1)        (       \
+       PPC_BITEXTRACT(srr1, 45, 0) |   \
+       PPC_BITEXTRACT(srr1, 44, 1) |   \
+       PPC_BITEXTRACT(srr1, 43, 2) |   \
+       PPC_BITEXTRACT(srr1, 36, 3) )
+
+/* 0 is reserved */
+#define P9_SRR1_MC_IFETCH_UE                           1
+#define P9_SRR1_MC_IFETCH_SLB_PARITY                   2
+#define P9_SRR1_MC_IFETCH_SLB_MULTIHIT                 3
+#define P9_SRR1_MC_IFETCH_ERAT_MULTIHIT                        4
+#define P9_SRR1_MC_IFETCH_TLB_MULTIHIT                 5
+#define P9_SRR1_MC_IFETCH_UE_TLB_RELOAD                        6
+/* 7 is reserved */
+#define P9_SRR1_MC_IFETCH_LINK_TIMEOUT                 8
+#define P9_SRR1_MC_IFETCH_LINK_TABLEWALK_TIMEOUT       9
+/* 10 ? */
+#define P9_SRR1_MC_IFETCH_RA                   11
+#define P9_SRR1_MC_IFETCH_RA_TABLEWALK         12
+#define P9_SRR1_MC_IFETCH_RA_ASYNC_STORE               13
+#define P9_SRR1_MC_IFETCH_LINK_ASYNC_STORE_TIMEOUT     14
+#define P9_SRR1_MC_IFETCH_RA_TABLEWALK_FOREIGN 15
+
+/* DSISR bits for machine check (On Power9) */
+#define P9_DSISR_MC_UE                                 (PPC_BIT(48))
+#define P9_DSISR_MC_UE_TABLEWALK                       (PPC_BIT(49))
+#define P9_DSISR_MC_LINK_LOAD_TIMEOUT                  (PPC_BIT(50))
+#define P9_DSISR_MC_LINK_TABLEWALK_TIMEOUT             (PPC_BIT(51))
+#define P9_DSISR_MC_ERAT_MULTIHIT                      (PPC_BIT(52))
+#define P9_DSISR_MC_TLB_MULTIHIT_MFTLB                 (PPC_BIT(53))
+#define P9_DSISR_MC_USER_TLBIE                         (PPC_BIT(54))
+#define P9_DSISR_MC_SLB_PARITY_MFSLB                   (PPC_BIT(55))
+#define P9_DSISR_MC_SLB_MULTIHIT_MFSLB                 (PPC_BIT(56))
+#define P9_DSISR_MC_RA_LOAD                            (PPC_BIT(57))
+#define P9_DSISR_MC_RA_TABLEWALK                       (PPC_BIT(58))
+#define P9_DSISR_MC_RA_TABLEWALK_FOREIGN               (PPC_BIT(59))
+#define P9_DSISR_MC_RA_FOREIGN                         (PPC_BIT(60))
+
+/* SLB error bits */
+#define P9_DSISR_MC_SLB_ERRORS         (P9_DSISR_MC_ERAT_MULTIHIT | \
+                                        P9_DSISR_MC_SLB_PARITY_MFSLB | \
+                                        P9_DSISR_MC_SLB_MULTIHIT_MFSLB)
+
 enum MCE_Version {
        MCE_V1 = 1,
 };
@@ -93,6 +142,9 @@ enum MCE_ErrorType {
        MCE_ERROR_TYPE_SLB = 2,
        MCE_ERROR_TYPE_ERAT = 3,
        MCE_ERROR_TYPE_TLB = 4,
+       MCE_ERROR_TYPE_USER = 5,
+       MCE_ERROR_TYPE_RA = 6,
+       MCE_ERROR_TYPE_LINK = 7,
 };
 
 enum MCE_UeErrorType {
@@ -121,6 +173,32 @@ enum MCE_TlbErrorType {
        MCE_TLB_ERROR_MULTIHIT = 2,
 };
 
+enum MCE_UserErrorType {
+       MCE_USER_ERROR_INDETERMINATE = 0,
+       MCE_USER_ERROR_TLBIE = 1,
+};
+
+enum MCE_RaErrorType {
+       MCE_RA_ERROR_INDETERMINATE = 0,
+       MCE_RA_ERROR_IFETCH = 1,
+       MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+       MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN = 3,
+       MCE_RA_ERROR_LOAD = 4,
+       MCE_RA_ERROR_STORE = 5,
+       MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 6,
+       MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN = 7,
+       MCE_RA_ERROR_LOAD_STORE_FOREIGN = 8,
+};
+
+enum MCE_LinkErrorType {
+       MCE_LINK_ERROR_INDETERMINATE = 0,
+       MCE_LINK_ERROR_IFETCH_TIMEOUT = 1,
+       MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT = 2,
+       MCE_LINK_ERROR_LOAD_TIMEOUT = 3,
+       MCE_LINK_ERROR_STORE_TIMEOUT = 4,
+       MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT = 5,
+};
+
 struct machine_check_event {
        enum MCE_Version        version:8;      /* 0x00 */
        uint8_t                 in_use;         /* 0x01 */
@@ -166,6 +244,30 @@ struct machine_check_event {
                        uint64_t        effective_address;
                        uint8_t         reserved_2[16];
                } tlb_error;
+
+               struct {
+                       enum MCE_UserErrorType user_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } user_error;
+
+               struct {
+                       enum MCE_RaErrorType ra_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } ra_error;
+
+               struct {
+                       enum MCE_LinkErrorType link_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } link_error;
        } u;
 };
 
@@ -176,8 +278,12 @@ struct mce_error_info {
                enum MCE_SlbErrorType slb_error_type:8;
                enum MCE_EratErrorType erat_error_type:8;
                enum MCE_TlbErrorType tlb_error_type:8;
+               enum MCE_UserErrorType user_error_type:8;
+               enum MCE_RaErrorType ra_error_type:8;
+               enum MCE_LinkErrorType link_error_type:8;
        } u;
-       uint8_t         reserved[2];
+       enum MCE_Severity       severity:8;
+       enum MCE_Initiator      initiator:8;
 };
 
 #define MAX_MC_EVT     100
index 4b369d83fe9ce1ea72b3f2a93590fb132d534512..1c9470881c4abe249fd943294c99e94f1916893b 100644 (file)
@@ -387,3 +387,4 @@ SYSCALL(copy_file_range)
 COMPAT_SYS_SPU(preadv2)
 COMPAT_SYS_SPU(pwritev2)
 SYSCALL(kexec_file_load)
+SYSCALL(statx)
index eb1acee91a2034c30d4277fe040cd797279f13b4..9ba11dbcaca98f88c53ee46c3bd009b22f13df01 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            383
+#define NR_syscalls            384
 
 #define __NR__exit __NR_exit
 
index 2f26335a3c42a8141d29156f07105ca82761a98c..b85f1422885746d918131216fb45fd76bb99338a 100644 (file)
 #define __NR_preadv2           380
 #define __NR_pwritev2          381
 #define __NR_kexec_file_load   382
+#define __NR_statx             383
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index bb7a1890aeb7fb8e95cf8ca0c7aa53765e12eb45..e79b9daa873c1874485021676426ea47196a5a68 100644 (file)
@@ -77,6 +77,7 @@ extern void __flush_tlb_power8(unsigned int action);
 extern void __flush_tlb_power9(unsigned int action);
 extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
 extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
+extern long __machine_check_early_realmode_p9(struct pt_regs *regs);
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_E500)
 extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
@@ -540,6 +541,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_power9,
                .cpu_restore            = __restore_cpu_power9,
                .flush_tlb              = __flush_tlb_power9,
+               .machine_check_early    = __machine_check_early_realmode_p9,
                .platform               = "power9",
        },
        {       /* Power9 */
@@ -559,6 +561,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_power9,
                .cpu_restore            = __restore_cpu_power9,
                .flush_tlb              = __flush_tlb_power9,
+               .machine_check_early    = __machine_check_early_realmode_p9,
                .platform               = "power9",
        },
        {       /* Cell Broadband Engine */
index 995728736677071512b5eb40f04bff0045bd2bbb..6fd08219248db7485a6d5c8227dee83664d29b38 100644 (file)
@@ -449,9 +449,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 _GLOBAL(pnv_wakeup_tb_loss)
        ld      r1,PACAR1(r13)
        /*
-        * Before entering any idle state, the NVGPRs are saved in the stack
-        * and they are restored before switching to the process context. Hence
-        * until they are restored, they are free to be used.
+        * Before entering any idle state, the NVGPRs are saved in the stack.
+        * If there was a state loss, or PACA_NAPSTATELOST was set, then the
+        * NVGPRs are restored. If we are here, it is likely that state is lost,
+        * but not guaranteed -- neither ISA207 nor ISA300 tests to reach
+        * here are the same as the test to restore NVGPRS:
+        * PACA_THREAD_IDLE_STATE test for ISA207, PSSCR test for ISA300,
+        * and SRR1 test for restoring NVGPRs.
+        *
+        * We are about to clobber NVGPRs now, so set NAPSTATELOST to
+        * guarantee they will always be restored. This might be tightened
+        * with careful reading of specs (particularly for ISA300) but this
+        * is already a slow wakeup path and it's simpler to be safe.
+        */
+       li      r0,1
+       stb     r0,PACA_NAPSTATELOST(r13)
+
+       /*
         *
         * Save SRR1 and LR in NVGPRs as they might be clobbered in
         * opal_call() (called in CHECK_HMI_INTERRUPT). SRR1 is required
index c6923ff451311bfade14e7f68888f85bb69f7176..a1475e6aef3a519c70824d4dd432748097a7965e 100644 (file)
@@ -58,6 +58,15 @@ static void mce_set_error_info(struct machine_check_event *mce,
        case MCE_ERROR_TYPE_TLB:
                mce->u.tlb_error.tlb_error_type = mce_err->u.tlb_error_type;
                break;
+       case MCE_ERROR_TYPE_USER:
+               mce->u.user_error.user_error_type = mce_err->u.user_error_type;
+               break;
+       case MCE_ERROR_TYPE_RA:
+               mce->u.ra_error.ra_error_type = mce_err->u.ra_error_type;
+               break;
+       case MCE_ERROR_TYPE_LINK:
+               mce->u.link_error.link_error_type = mce_err->u.link_error_type;
+               break;
        case MCE_ERROR_TYPE_UNKNOWN:
        default:
                break;
@@ -90,13 +99,14 @@ void save_mce_event(struct pt_regs *regs, long handled,
        mce->gpr3 = regs->gpr[3];
        mce->in_use = 1;
 
-       mce->initiator = MCE_INITIATOR_CPU;
        /* Mark it recovered if we have handled it and MSR(RI=1). */
        if (handled && (regs->msr & MSR_RI))
                mce->disposition = MCE_DISPOSITION_RECOVERED;
        else
                mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
-       mce->severity = MCE_SEV_ERROR_SYNC;
+
+       mce->initiator = mce_err->initiator;
+       mce->severity = mce_err->severity;
 
        /*
         * Populate the mce error_type and type-specific error_type.
@@ -115,6 +125,15 @@ void save_mce_event(struct pt_regs *regs, long handled,
        } else if (mce->error_type == MCE_ERROR_TYPE_ERAT) {
                mce->u.erat_error.effective_address_provided = true;
                mce->u.erat_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_USER) {
+               mce->u.user_error.effective_address_provided = true;
+               mce->u.user_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_RA) {
+               mce->u.ra_error.effective_address_provided = true;
+               mce->u.ra_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_LINK) {
+               mce->u.link_error.effective_address_provided = true;
+               mce->u.link_error.effective_address = addr;
        } else if (mce->error_type == MCE_ERROR_TYPE_UE) {
                mce->u.ue_error.effective_address_provided = true;
                mce->u.ue_error.effective_address = addr;
@@ -239,6 +258,29 @@ void machine_check_print_event_info(struct machine_check_event *evt)
                "Parity",
                "Multihit",
        };
+       static const char *mc_user_types[] = {
+               "Indeterminate",
+               "tlbie(l) invalid",
+       };
+       static const char *mc_ra_types[] = {
+               "Indeterminate",
+               "Instruction fetch (bad)",
+               "Page table walk ifetch (bad)",
+               "Page table walk ifetch (foreign)",
+               "Load (bad)",
+               "Store (bad)",
+               "Page table walk Load/Store (bad)",
+               "Page table walk Load/Store (foreign)",
+               "Load/Store (foreign)",
+       };
+       static const char *mc_link_types[] = {
+               "Indeterminate",
+               "Instruction fetch (timeout)",
+               "Page table walk ifetch (timeout)",
+               "Load (timeout)",
+               "Store (timeout)",
+               "Page table walk Load/Store (timeout)",
+       };
 
        /* Print things out */
        if (evt->version != MCE_V1) {
@@ -315,6 +357,36 @@ void machine_check_print_event_info(struct machine_check_event *evt)
                        printk("%s    Effective address: %016llx\n",
                               level, evt->u.tlb_error.effective_address);
                break;
+       case MCE_ERROR_TYPE_USER:
+               subtype = evt->u.user_error.user_error_type <
+                       ARRAY_SIZE(mc_user_types) ?
+                       mc_user_types[evt->u.user_error.user_error_type]
+                       : "Unknown";
+               printk("%s  Error type: User [%s]\n", level, subtype);
+               if (evt->u.user_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.user_error.effective_address);
+               break;
+       case MCE_ERROR_TYPE_RA:
+               subtype = evt->u.ra_error.ra_error_type <
+                       ARRAY_SIZE(mc_ra_types) ?
+                       mc_ra_types[evt->u.ra_error.ra_error_type]
+                       : "Unknown";
+               printk("%s  Error type: Real address [%s]\n", level, subtype);
+               if (evt->u.ra_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.ra_error.effective_address);
+               break;
+       case MCE_ERROR_TYPE_LINK:
+               subtype = evt->u.link_error.link_error_type <
+                       ARRAY_SIZE(mc_link_types) ?
+                       mc_link_types[evt->u.link_error.link_error_type]
+                       : "Unknown";
+               printk("%s  Error type: Link [%s]\n", level, subtype);
+               if (evt->u.link_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.link_error.effective_address);
+               break;
        default:
        case MCE_ERROR_TYPE_UNKNOWN:
                printk("%s  Error type: Unknown\n", level);
@@ -341,6 +413,18 @@ uint64_t get_mce_fault_addr(struct machine_check_event *evt)
                if (evt->u.tlb_error.effective_address_provided)
                        return evt->u.tlb_error.effective_address;
                break;
+       case MCE_ERROR_TYPE_USER:
+               if (evt->u.user_error.effective_address_provided)
+                       return evt->u.user_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_RA:
+               if (evt->u.ra_error.effective_address_provided)
+                       return evt->u.ra_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_LINK:
+               if (evt->u.link_error.effective_address_provided)
+                       return evt->u.link_error.effective_address;
+               break;
        default:
        case MCE_ERROR_TYPE_UNKNOWN:
                break;
index 7353991c4ecee6d8a6ecacdce4ab96815ffdfb12..763d6f58caa8ca140c8afb1260555b0ea1c1d2a0 100644 (file)
@@ -116,6 +116,51 @@ static void flush_and_reload_slb(void)
 }
 #endif
 
+static void flush_erat(void)
+{
+       asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
+}
+
+#define MCE_FLUSH_SLB 1
+#define MCE_FLUSH_TLB 2
+#define MCE_FLUSH_ERAT 3
+
+static int mce_flush(int what)
+{
+#ifdef CONFIG_PPC_STD_MMU_64
+       if (what == MCE_FLUSH_SLB) {
+               flush_and_reload_slb();
+               return 1;
+       }
+#endif
+       if (what == MCE_FLUSH_ERAT) {
+               flush_erat();
+               return 1;
+       }
+       if (what == MCE_FLUSH_TLB) {
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb) {
+                       cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_GLOBAL);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int mce_handle_flush_derrors(uint64_t dsisr, uint64_t slb, uint64_t tlb, uint64_t erat)
+{
+       if ((dsisr & slb) && mce_flush(MCE_FLUSH_SLB))
+               dsisr &= ~slb;
+       if ((dsisr & erat) && mce_flush(MCE_FLUSH_ERAT))
+               dsisr &= ~erat;
+       if ((dsisr & tlb) && mce_flush(MCE_FLUSH_TLB))
+               dsisr &= ~tlb;
+       /* Any other errors we don't understand? */
+       if (dsisr)
+               return 0;
+       return 1;
+}
+
 static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits)
 {
        long handled = 1;
@@ -281,6 +326,9 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
        long handled = 1;
        struct mce_error_info mce_error_info = { 0 };
 
+       mce_error_info.severity = MCE_SEV_ERROR_SYNC;
+       mce_error_info.initiator = MCE_INITIATOR_CPU;
+
        srr1 = regs->msr;
        nip = regs->nip;
 
@@ -352,6 +400,9 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs)
        long handled = 1;
        struct mce_error_info mce_error_info = { 0 };
 
+       mce_error_info.severity = MCE_SEV_ERROR_SYNC;
+       mce_error_info.initiator = MCE_INITIATOR_CPU;
+
        srr1 = regs->msr;
        nip = regs->nip;
 
@@ -372,3 +423,189 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs)
        save_mce_event(regs, handled, &mce_error_info, nip, addr);
        return handled;
 }
+
+static int mce_handle_derror_p9(struct pt_regs *regs)
+{
+       uint64_t dsisr = regs->dsisr;
+
+       return mce_handle_flush_derrors(dsisr,
+                       P9_DSISR_MC_SLB_PARITY_MFSLB |
+                       P9_DSISR_MC_SLB_MULTIHIT_MFSLB,
+
+                       P9_DSISR_MC_TLB_MULTIHIT_MFTLB,
+
+                       P9_DSISR_MC_ERAT_MULTIHIT);
+}
+
+static int mce_handle_ierror_p9(struct pt_regs *regs)
+{
+       uint64_t srr1 = regs->msr;
+
+       switch (P9_SRR1_MC_IFETCH(srr1)) {
+       case P9_SRR1_MC_IFETCH_SLB_PARITY:
+       case P9_SRR1_MC_IFETCH_SLB_MULTIHIT:
+               return mce_flush(MCE_FLUSH_SLB);
+       case P9_SRR1_MC_IFETCH_TLB_MULTIHIT:
+               return mce_flush(MCE_FLUSH_TLB);
+       case P9_SRR1_MC_IFETCH_ERAT_MULTIHIT:
+               return mce_flush(MCE_FLUSH_ERAT);
+       default:
+               return 0;
+       }
+}
+
+static void mce_get_derror_p9(struct pt_regs *regs,
+               struct mce_error_info *mce_err, uint64_t *addr)
+{
+       uint64_t dsisr = regs->dsisr;
+
+       mce_err->severity = MCE_SEV_ERROR_SYNC;
+       mce_err->initiator = MCE_INITIATOR_CPU;
+
+       if (dsisr & P9_DSISR_MC_USER_TLBIE)
+               *addr = regs->nip;
+       else
+               *addr = regs->dar;
+
+       if (dsisr & P9_DSISR_MC_UE) {
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_LOAD_STORE;
+       } else if (dsisr & P9_DSISR_MC_UE_TABLEWALK) {
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE;
+       } else if (dsisr & P9_DSISR_MC_LINK_LOAD_TIMEOUT) {
+               mce_err->error_type = MCE_ERROR_TYPE_LINK;
+               mce_err->u.link_error_type = MCE_LINK_ERROR_LOAD_TIMEOUT;
+       } else if (dsisr & P9_DSISR_MC_LINK_TABLEWALK_TIMEOUT) {
+               mce_err->error_type = MCE_ERROR_TYPE_LINK;
+               mce_err->u.link_error_type = MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT;
+       } else if (dsisr & P9_DSISR_MC_ERAT_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       } else if (dsisr & P9_DSISR_MC_TLB_MULTIHIT_MFTLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_TLB;
+               mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+       } else if (dsisr & P9_DSISR_MC_USER_TLBIE) {
+               mce_err->error_type = MCE_ERROR_TYPE_USER;
+               mce_err->u.user_error_type = MCE_USER_ERROR_TLBIE;
+       } else if (dsisr & P9_DSISR_MC_SLB_PARITY_MFSLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
+       } else if (dsisr & P9_DSISR_MC_SLB_MULTIHIT_MFSLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+       } else if (dsisr & P9_DSISR_MC_RA_LOAD) {
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_LOAD;
+       } else if (dsisr & P9_DSISR_MC_RA_TABLEWALK) {
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE;
+       } else if (dsisr & P9_DSISR_MC_RA_TABLEWALK_FOREIGN) {
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN;
+       } else if (dsisr & P9_DSISR_MC_RA_FOREIGN) {
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_LOAD_STORE_FOREIGN;
+       }
+}
+
+static void mce_get_ierror_p9(struct pt_regs *regs,
+               struct mce_error_info *mce_err, uint64_t *addr)
+{
+       uint64_t srr1 = regs->msr;
+
+       switch (P9_SRR1_MC_IFETCH(srr1)) {
+       case P9_SRR1_MC_IFETCH_RA_ASYNC_STORE:
+       case P9_SRR1_MC_IFETCH_LINK_ASYNC_STORE_TIMEOUT:
+               mce_err->severity = MCE_SEV_FATAL;
+               break;
+       default:
+               mce_err->severity = MCE_SEV_ERROR_SYNC;
+               break;
+       }
+
+       mce_err->initiator = MCE_INITIATOR_CPU;
+
+       *addr = regs->nip;
+
+       switch (P9_SRR1_MC_IFETCH(srr1)) {
+       case P9_SRR1_MC_IFETCH_UE:
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_IFETCH;
+               break;
+       case P9_SRR1_MC_IFETCH_SLB_PARITY:
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
+               break;
+       case P9_SRR1_MC_IFETCH_SLB_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+               break;
+       case P9_SRR1_MC_IFETCH_ERAT_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+               break;
+       case P9_SRR1_MC_IFETCH_TLB_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_TLB;
+               mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+               break;
+       case P9_SRR1_MC_IFETCH_UE_TLB_RELOAD:
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH;
+               break;
+       case P9_SRR1_MC_IFETCH_LINK_TIMEOUT:
+               mce_err->error_type = MCE_ERROR_TYPE_LINK;
+               mce_err->u.link_error_type = MCE_LINK_ERROR_IFETCH_TIMEOUT;
+               break;
+       case P9_SRR1_MC_IFETCH_LINK_TABLEWALK_TIMEOUT:
+               mce_err->error_type = MCE_ERROR_TYPE_LINK;
+               mce_err->u.link_error_type = MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT;
+               break;
+       case P9_SRR1_MC_IFETCH_RA:
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_IFETCH;
+               break;
+       case P9_SRR1_MC_IFETCH_RA_TABLEWALK:
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH;
+               break;
+       case P9_SRR1_MC_IFETCH_RA_ASYNC_STORE:
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_STORE;
+               break;
+       case P9_SRR1_MC_IFETCH_LINK_ASYNC_STORE_TIMEOUT:
+               mce_err->error_type = MCE_ERROR_TYPE_LINK;
+               mce_err->u.link_error_type = MCE_LINK_ERROR_STORE_TIMEOUT;
+               break;
+       case P9_SRR1_MC_IFETCH_RA_TABLEWALK_FOREIGN:
+               mce_err->error_type = MCE_ERROR_TYPE_RA;
+               mce_err->u.ra_error_type = MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN;
+               break;
+       default:
+               break;
+       }
+}
+
+long __machine_check_early_realmode_p9(struct pt_regs *regs)
+{
+       uint64_t nip, addr;
+       long handled;
+       struct mce_error_info mce_error_info = { 0 };
+
+       nip = regs->nip;
+
+       if (P9_SRR1_MC_LOADSTORE(regs->msr)) {
+               handled = mce_handle_derror_p9(regs);
+               mce_get_derror_p9(regs, &mce_error_info, &addr);
+       } else {
+               handled = mce_handle_ierror_p9(regs);
+               mce_get_ierror_p9(regs, &mce_error_info, &addr);
+       }
+
+       /* Handle UE error. */
+       if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
+               handled = mce_handle_ue_error(regs);
+
+       save_mce_event(regs, handled, &mce_error_info, nip, addr);
+       return handled;
+}
index 9be992083d2a7f7103d6ef9a251e95a207d41dd0..c22f207aa6564ba93df40ecc03713de04cb20f99 100644 (file)
@@ -397,8 +397,7 @@ static void early_check_vec5(void)
 void __init mmu_early_init_devtree(void)
 {
        /* Disable radix mode based on kernel command line. */
-       /* We don't yet have the machinery to do radix as a guest. */
-       if (disable_radix || !(mfmsr() & MSR_HV))
+       if (disable_radix)
                cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
 
        /*
index 595dd718ea8718b010fed1ca5c08f5f121f674c0..2ff13249f87a61759f015d7fff93bd014dba6347 100644 (file)
@@ -188,6 +188,8 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
                        sdsync = POWER7P_MMCRA_SDAR_VALID;
                else if (ppmu->flags & PPMU_ALT_SIPR)
                        sdsync = POWER6_MMCRA_SDSYNC;
+               else if (ppmu->flags & PPMU_NO_SIAR)
+                       sdsync = MMCRA_SAMPLE_ENABLE;
                else
                        sdsync = MMCRA_SDSYNC;
 
index e79fb5fb817dbe21cd19f633d89ca3bbbf51ad0c..cd951fd231c4040ba653f32cf485eebb22d1d805 100644 (file)
@@ -65,12 +65,41 @@ static bool is_event_valid(u64 event)
        return !(event & ~valid_mask);
 }
 
-static u64 mmcra_sdar_mode(u64 event)
+static inline bool is_event_marked(u64 event)
 {
-       if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
-               return p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT;
+       if (event & EVENT_IS_MARKED)
+               return true;
+
+       return false;
+}
 
-       return MMCRA_SDAR_MODE_TLB;
+static void mmcra_sdar_mode(u64 event, unsigned long *mmcra)
+{
+       /*
+        * MMCRA[SDAR_MODE] specifices how the SDAR should be updated in
+        * continous sampling mode.
+        *
+        * Incase of Power8:
+        * MMCRA[SDAR_MODE] will be programmed as "0b01" for continous sampling
+        * mode and will be un-changed when setting MMCRA[63] (Marked events).
+        *
+        * Incase of Power9:
+        * Marked event: MMCRA[SDAR_MODE] will be set to 0b00 ('No Updates'),
+        *               or if group already have any marked events.
+        * Non-Marked events (for DD1):
+        *      MMCRA[SDAR_MODE] will be set to 0b01
+        * For rest
+        *      MMCRA[SDAR_MODE] will be set from event code.
+        */
+       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+               if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE))
+                       *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES;
+               else if (!cpu_has_feature(CPU_FTR_POWER9_DD1))
+                       *mmcra |=  p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT;
+               else if (cpu_has_feature(CPU_FTR_POWER9_DD1))
+                       *mmcra |= MMCRA_SDAR_MODE_TLB;
+       } else
+               *mmcra |= MMCRA_SDAR_MODE_TLB;
 }
 
 static u64 thresh_cmp_val(u64 value)
@@ -180,7 +209,7 @@ int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
                value |= CNST_L1_QUAL_VAL(cache);
        }
 
-       if (event & EVENT_IS_MARKED) {
+       if (is_event_marked(event)) {
                mask  |= CNST_SAMPLE_MASK;
                value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT);
        }
@@ -276,7 +305,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev,
                }
 
                /* In continuous sampling mode, update SDAR on TLB miss */
-               mmcra |= mmcra_sdar_mode(event[i]);
+               mmcra_sdar_mode(event[i], &mmcra);
 
                if (event[i] & EVENT_IS_L1) {
                        cache = event[i] >> EVENT_CACHE_SEL_SHIFT;
@@ -285,7 +314,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev,
                        mmcr1 |= (cache & 1) << MMCR1_DC_QUAL_SHIFT;
                }
 
-               if (event[i] & EVENT_IS_MARKED) {
+               if (is_event_marked(event[i])) {
                        mmcra |= MMCRA_SAMPLE_ENABLE;
 
                        val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK;
index cf9bd89901595cc38b793bc916a2096d873054eb..899210f14ee432ea4b63cc7de6f7ea1a6da7a404 100644 (file)
 #define MMCRA_THR_CMP_SHIFT            32
 #define MMCRA_SDAR_MODE_SHIFT          42
 #define MMCRA_SDAR_MODE_TLB            (1ull << MMCRA_SDAR_MODE_SHIFT)
+#define MMCRA_SDAR_MODE_NO_UPDATES     ~(0x3ull << MMCRA_SDAR_MODE_SHIFT)
 #define MMCRA_IFM_SHIFT                        30
 
 /* MMCR1 Threshold Compare bit constant for power9 */
index 86d9fde93c175f86dac6f40de0d68aff2455b0c6..e0f856bfbfe8f3c6ecfa70e737b1b2496725d563 100644 (file)
@@ -395,7 +395,6 @@ static int opal_recover_mce(struct pt_regs *regs,
                                        struct machine_check_event *evt)
 {
        int recovered = 0;
-       uint64_t ea = get_mce_fault_addr(evt);
 
        if (!(regs->msr & MSR_RI)) {
                /* If MSR_RI isn't set, we cannot recover */
@@ -404,26 +403,18 @@ static int opal_recover_mce(struct pt_regs *regs,
        } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
                /* Platform corrected itself */
                recovered = 1;
-       } else if (ea && !is_kernel_addr(ea)) {
+       } else if (evt->severity == MCE_SEV_FATAL) {
+               /* Fatal machine check */
+               pr_err("Machine check interrupt is fatal\n");
+               recovered = 0;
+       } else if ((evt->severity == MCE_SEV_ERROR_SYNC) &&
+                       (user_mode(regs) && !is_global_init(current))) {
                /*
-                * Faulting address is not in kernel text. We should be fine.
-                * We need to find which process uses this address.
                 * For now, kill the task if we have received exception when
                 * in userspace.
                 *
                 * TODO: Queue up this address for hwpoisioning later.
                 */
-               if (user_mode(regs) && !is_global_init(current)) {
-                       _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
-                       recovered = 1;
-               } else
-                       recovered = 0;
-       } else if (user_mode(regs) && !is_global_init(current) &&
-               evt->severity == MCE_SEV_ERROR_SYNC) {
-               /*
-                * If we have received a synchronous error when in userspace
-                * kill the task.
-                */
                _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
                recovered = 1;
        }
index 6901a06da2f90bddf70386667eaea5c4fe3505a7..e36738291c320575523422e139d4642e04142bd5 100644 (file)
@@ -1775,17 +1775,20 @@ static u64 pnv_pci_ioda_dma_get_required_mask(struct pci_dev *pdev)
 }
 
 static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
-                                  struct pci_bus *bus)
+                                  struct pci_bus *bus,
+                                  bool add_to_group)
 {
        struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                set_iommu_table_base(&dev->dev, pe->table_group.tables[0]);
                set_dma_offset(&dev->dev, pe->tce_bypass_base);
-               iommu_add_device(&dev->dev);
+               if (add_to_group)
+                       iommu_add_device(&dev->dev);
 
                if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
-                       pnv_ioda_setup_bus_dma(pe, dev->subordinate);
+                       pnv_ioda_setup_bus_dma(pe, dev->subordinate,
+                                       add_to_group);
        }
 }
 
@@ -2191,7 +2194,7 @@ found:
                set_iommu_table_base(&pe->pdev->dev, tbl);
                iommu_add_device(&pe->pdev->dev);
        } else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))
-               pnv_ioda_setup_bus_dma(pe, pe->pbus);
+               pnv_ioda_setup_bus_dma(pe, pe->pbus, true);
 
        return;
  fail:
@@ -2426,6 +2429,8 @@ static void pnv_ioda2_take_ownership(struct iommu_table_group *table_group)
 
        pnv_pci_ioda2_set_bypass(pe, false);
        pnv_pci_ioda2_unset_window(&pe->table_group, 0);
+       if (pe->pbus)
+               pnv_ioda_setup_bus_dma(pe, pe->pbus, false);
        pnv_ioda2_table_free(tbl);
 }
 
@@ -2435,6 +2440,8 @@ static void pnv_ioda2_release_ownership(struct iommu_table_group *table_group)
                                                table_group);
 
        pnv_pci_ioda2_setup_default_config(pe);
+       if (pe->pbus)
+               pnv_ioda_setup_bus_dma(pe, pe->pbus, false);
 }
 
 static struct iommu_table_group_ops pnv_pci_ioda2_ops = {
@@ -2624,6 +2631,9 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
        level_shift = entries_shift + 3;
        level_shift = max_t(unsigned, level_shift, PAGE_SHIFT);
 
+       if ((level_shift - 3) * levels + page_shift >= 60)
+               return -EINVAL;
+
        /* Allocate TCE table */
        addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
                        levels, tce_table_size, &offset, &total_allocated);
@@ -2728,7 +2738,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
        if (pe->flags & PNV_IODA_PE_DEV)
                iommu_add_device(&pe->pdev->dev);
        else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))
-               pnv_ioda_setup_bus_dma(pe, pe->pbus);
+               pnv_ioda_setup_bus_dma(pe, pe->pbus, true);
 }
 
 #ifdef CONFIG_PCI_MSI
index 251060cf171364f1dd4dd08452189133dd713265..8b1fe895daa3f076bf57b6b9fe3283a6ba686fad 100644 (file)
@@ -751,7 +751,9 @@ void __init hpte_init_pseries(void)
        mmu_hash_ops.flush_hash_range    = pSeries_lpar_flush_hash_range;
        mmu_hash_ops.hpte_clear_all      = pseries_hpte_clear_all;
        mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
-       mmu_hash_ops.resize_hpt          = pseries_lpar_resize_hpt;
+
+       if (firmware_has_feature(FW_FEATURE_HPT_RESIZE))
+               mmu_hash_ops.resize_hpt = pseries_lpar_resize_hpt;
 }
 
 void radix_init_pseries(void)
index 349d4d17aa7fbd3a6268be3bd6e7bea909e76ccf..2aa1ad194db21a541f65c30b65fe20f2806fdff3 100644 (file)
@@ -2101,8 +2101,8 @@ static int x86_pmu_event_init(struct perf_event *event)
 
 static void refresh_pce(void *ignored)
 {
-       if (current->mm)
-               load_mm_cr4(current->mm);
+       if (current->active_mm)
+               load_mm_cr4(current->active_mm);
 }
 
 static void x86_pmu_event_mapped(struct perf_event *event)
@@ -2110,6 +2110,18 @@ static void x86_pmu_event_mapped(struct perf_event *event)
        if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
                return;
 
+       /*
+        * This function relies on not being called concurrently in two
+        * tasks in the same mm.  Otherwise one task could observe
+        * perf_rdpmc_allowed > 1 and return all the way back to
+        * userspace with CR4.PCE clear while another task is still
+        * doing on_each_cpu_mask() to propagate CR4.PCE.
+        *
+        * For now, this can't happen because all callers hold mmap_sem
+        * for write.  If this changes, we'll need a different solution.
+        */
+       lockdep_assert_held_exclusive(&current->mm->mmap_sem);
+
        if (atomic_inc_return(&current->mm->context.perf_rdpmc_allowed) == 1)
                on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);
 }
index 72277b1028a5f54551962555fa56bfd5aebab15c..50d35e3185f553b92ce1eeba2700f13e33e49258 100644 (file)
@@ -121,12 +121,9 @@ static inline void native_pmd_clear(pmd_t *pmd)
        *(tmp + 1) = 0;
 }
 
-#if !defined(CONFIG_SMP) || (defined(CONFIG_HIGHMEM64G) && \
-               defined(CONFIG_PARAVIRT))
 static inline void native_pud_clear(pud_t *pudp)
 {
 }
-#endif
 
 static inline void pud_clear(pud_t *pudp)
 {
index 1cfb36b8c024ab07b8334121fc56ac79f2a35371..585ee0d42d18fc162601ff0d8a53827f0d011f5e 100644 (file)
@@ -62,7 +62,7 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page);
 # define set_pud(pudp, pud)            native_set_pud(pudp, pud)
 #endif
 
-#ifndef __PAGETABLE_PMD_FOLDED
+#ifndef __PAGETABLE_PUD_FOLDED
 #define pud_clear(pud)                 native_pud_clear(pud)
 #endif
 
index ae32838cac5fd2251e1ffa0bbb8b8c629e399a84..b2879cc23db470ec8cc2cbeacdea4ff2b94ec1e3 100644 (file)
@@ -179,10 +179,15 @@ static int acpi_register_lapic(int id, u32 acpiid, u8 enabled)
                return -EINVAL;
        }
 
+       if (!enabled) {
+               ++disabled_cpus;
+               return -EINVAL;
+       }
+
        if (boot_cpu_physical_apicid != -1U)
                ver = boot_cpu_apic_version;
 
-       cpu = __generic_processor_info(id, ver, enabled);
+       cpu = generic_processor_info(id, ver);
        if (cpu >= 0)
                early_per_cpu(x86_cpu_to_acpiid, cpu) = acpiid;
 
@@ -710,7 +715,7 @@ static void __init acpi_set_irq_model_ioapic(void)
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 #include <acpi/processor.h>
 
-int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
+static int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
        int nid;
index aee7deddabd089b31bef1739c51a7972e04cb10d..8ccb7ef512e05dd9edaa6a3d7a852f70639a54d2 100644 (file)
@@ -2063,7 +2063,7 @@ static int allocate_logical_cpuid(int apicid)
        return nr_logical_cpuids++;
 }
 
-int __generic_processor_info(int apicid, int version, bool enabled)
+int generic_processor_info(int apicid, int version)
 {
        int cpu, max = nr_cpu_ids;
        bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
@@ -2121,11 +2121,9 @@ int __generic_processor_info(int apicid, int version, bool enabled)
        if (num_processors >= nr_cpu_ids) {
                int thiscpu = max + disabled_cpus;
 
-               if (enabled) {
-                       pr_warning("APIC: NR_CPUS/possible_cpus limit of %i "
-                                  "reached. Processor %d/0x%x ignored.\n",
-                                  max, thiscpu, apicid);
-               }
+               pr_warning("APIC: NR_CPUS/possible_cpus limit of %i "
+                          "reached. Processor %d/0x%x ignored.\n",
+                          max, thiscpu, apicid);
 
                disabled_cpus++;
                return -EINVAL;
@@ -2177,23 +2175,13 @@ int __generic_processor_info(int apicid, int version, bool enabled)
                apic->x86_32_early_logical_apicid(cpu);
 #endif
        set_cpu_possible(cpu, true);
-
-       if (enabled) {
-               num_processors++;
-               physid_set(apicid, phys_cpu_present_map);
-               set_cpu_present(cpu, true);
-       } else {
-               disabled_cpus++;
-       }
+       physid_set(apicid, phys_cpu_present_map);
+       set_cpu_present(cpu, true);
+       num_processors++;
 
        return cpu;
 }
 
-int generic_processor_info(int apicid, int version)
-{
-       return __generic_processor_info(apicid, version, true);
-}
-
 int hard_smp_processor_id(void)
 {
        return read_apic_id();
index c05509d38b1f1e5ed0f63940dc2c8496b360b032..9ac2a5cdd9c206e83f171847ac04d5bf4f2a3152 100644 (file)
@@ -727,7 +727,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn)
        if (atomic_dec_and_test(&rdtgrp->waitcount) &&
            (rdtgrp->flags & RDT_DELETED)) {
                kernfs_unbreak_active_protection(kn);
-               kernfs_put(kn);
+               kernfs_put(rdtgrp->kn);
                kfree(rdtgrp);
        } else {
                kernfs_unbreak_active_protection(kn);
index 54a2372f5dbb1eb0598788e944ad28708b638671..b5785c197e534796d5e477b6cd86a502d229db7c 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
  */
 
+#define DISABLE_BRANCH_PROFILING
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
index f088ea4c66e72e5787e6c2052b09bc95291cf131..a723ae9440ab2585303457dac977e53961f3cffd 100644 (file)
@@ -166,11 +166,9 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action)
        spin_lock_irqsave(&desc->lock, flags);
 
        /*
-        * most handlers of type NMI_UNKNOWN never return because
-        * they just assume the NMI is theirs.  Just a sanity check
-        * to manage expectations
+        * Indicate if there are multiple registrations on the
+        * internal NMI handler call chains (SERR and IO_CHECK).
         */
-       WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head));
        WARN_ON_ONCE(type == NMI_SERR && !list_empty(&desc->head));
        WARN_ON_ONCE(type == NMI_IO_CHECK && !list_empty(&desc->head));
 
index 4f7a9833d8e51f2e023c3a5c0f6b54813c70c4a0..c73a7f9e881aa25852cd4a1aa58950ee9bd79149 100644 (file)
@@ -1333,6 +1333,8 @@ static int __init init_tsc_clocksource(void)
         * the refined calibration and directly register it as a clocksource.
         */
        if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
+               if (boot_cpu_has(X86_FEATURE_ART))
+                       art_related_clocksource = &clocksource_tsc;
                clocksource_register_khz(&clocksource_tsc, tsc_khz);
                return 0;
        }
index 478d15dbaee41b251c8bb28b59183e2b6c733326..08339262b666e56f2623406a10c42f3184c83e29 100644 (file)
@@ -82,19 +82,43 @@ static size_t regs_size(struct pt_regs *regs)
        return sizeof(*regs);
 }
 
+#ifdef CONFIG_X86_32
+#define GCC_REALIGN_WORDS 3
+#else
+#define GCC_REALIGN_WORDS 1
+#endif
+
 static bool is_last_task_frame(struct unwind_state *state)
 {
-       unsigned long bp = (unsigned long)state->bp;
-       unsigned long regs = (unsigned long)task_pt_regs(state->task);
+       unsigned long *last_bp = (unsigned long *)task_pt_regs(state->task) - 2;
+       unsigned long *aligned_bp = last_bp - GCC_REALIGN_WORDS;
 
        /*
         * We have to check for the last task frame at two different locations
         * because gcc can occasionally decide to realign the stack pointer and
-        * change the offset of the stack frame by a word in the prologue of a
-        * function called by head/entry code.
+        * change the offset of the stack frame in the prologue of a function
+        * called by head/entry code.  Examples:
+        *
+        * <start_secondary>:
+        *      push   %edi
+        *      lea    0x8(%esp),%edi
+        *      and    $0xfffffff8,%esp
+        *      pushl  -0x4(%edi)
+        *      push   %ebp
+        *      mov    %esp,%ebp
+        *
+        * <x86_64_start_kernel>:
+        *      lea    0x8(%rsp),%r10
+        *      and    $0xfffffffffffffff0,%rsp
+        *      pushq  -0x8(%r10)
+        *      push   %rbp
+        *      mov    %rsp,%rbp
+        *
+        * Note that after aligning the stack, it pushes a duplicate copy of
+        * the return address before pushing the frame pointer.
         */
-       return bp == regs - FRAME_HEADER_SIZE ||
-              bp == regs - FRAME_HEADER_SIZE - sizeof(long);
+       return (state->bp == last_bp ||
+               (state->bp == aligned_bp && *(aligned_bp+1) == *(last_bp+1)));
 }
 
 /*
index 8d63d7a104c3c445805dcf24a59fff2756a17b01..4c90cfdc128b832c6065cdb8830f89d16bff63dd 100644 (file)
@@ -1,3 +1,4 @@
+#define DISABLE_BRANCH_PROFILING
 #define pr_fmt(fmt) "kasan: " fmt
 #include <linux/bootmem.h>
 #include <linux/kasan.h>
index 5126dfd52b182dd66471a49a0464eb2411fbc7cd..cd44ae727df7f48ceba7fad00591c48cec151896 100644 (file)
@@ -590,7 +590,7 @@ static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm,
  * we might run off the end of the bounds table if we are on
  * a 64-bit kernel and try to get 8 bytes.
  */
-int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret,
+static int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret,
                long __user *bd_entry_ptr)
 {
        u32 bd_entry_32;
index a7dbec4dce2758261c6e1680b7ed825e5e44a9d1..3dbde04febdccab382bc47ccba53b422ac7c72ea 100644 (file)
@@ -26,5 +26,6 @@ obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_pcal9555a.o
 obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o
 # MISC Devices
 obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o
+obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_mrfld_power_btn.o
 obj-$(subst m,y,$(CONFIG_RTC_DRV_CMOS)) += platform_mrfld_rtc.o
 obj-$(subst m,y,$(CONFIG_INTEL_MID_WATCHDOG)) += platform_mrfld_wdt.o
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_power_btn.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_power_btn.c
new file mode 100644 (file)
index 0000000..a6c3705
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Intel Merrifield power button support
+ *
+ * (C) Copyright 2017 Intel Corporation
+ *
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/sfi.h>
+
+#include <asm/intel-mid.h>
+#include <asm/intel_scu_ipc.h>
+
+static struct resource mrfld_power_btn_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device mrfld_power_btn_dev = {
+       .name           = "msic_power_btn",
+       .id             = PLATFORM_DEVID_NONE,
+       .num_resources  = ARRAY_SIZE(mrfld_power_btn_resources),
+       .resource       = mrfld_power_btn_resources,
+};
+
+static int mrfld_power_btn_scu_status_change(struct notifier_block *nb,
+                                            unsigned long code, void *data)
+{
+       if (code == SCU_DOWN) {
+               platform_device_unregister(&mrfld_power_btn_dev);
+               return 0;
+       }
+
+       return platform_device_register(&mrfld_power_btn_dev);
+}
+
+static struct notifier_block mrfld_power_btn_scu_notifier = {
+       .notifier_call  = mrfld_power_btn_scu_status_change,
+};
+
+static int __init register_mrfld_power_btn(void)
+{
+       if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
+               return -ENODEV;
+
+       /*
+        * We need to be sure that the SCU IPC is ready before
+        * PMIC power button device can be registered:
+        */
+       intel_scu_notifier_add(&mrfld_power_btn_scu_notifier);
+
+       return 0;
+}
+arch_initcall(register_mrfld_power_btn);
+
+static void __init *mrfld_power_btn_platform_data(void *info)
+{
+       struct resource *res = mrfld_power_btn_resources;
+       struct sfi_device_table_entry *pentry = info;
+
+       res->start = res->end = pentry->irq;
+       return NULL;
+}
+
+static const struct devs_id mrfld_power_btn_dev_id __initconst = {
+       .name                   = "bcove_power_btn",
+       .type                   = SFI_DEV_TYPE_IPC,
+       .delay                  = 1,
+       .msic                   = 1,
+       .get_platform_data      = &mrfld_power_btn_platform_data,
+};
+
+sfi_device(mrfld_power_btn_dev_id);
index 86edd1e941eb07bc46187024ae332409c6924073..9e304e2ea4f55c456e7f0037a8963f6586ad2b19 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/intel_scu_ipc.h>
 #include <asm/io_apic.h>
 
-#define TANGIER_EXT_TIMER0_MSI 15
+#define TANGIER_EXT_TIMER0_MSI 12
 
 static struct platform_device wdt_dev = {
        .name = "intel_mid_wdt",
index e793fe509971f49fb2cfa6a12f8b365a937ae206..e42978d4deafeb184ea8595eb0cf3ef54ceb62bc 100644 (file)
 
 #include "intel_mid_weak_decls.h"
 
-static void penwell_arch_setup(void);
-/* penwell arch ops */
-static struct intel_mid_ops penwell_ops = {
-       .arch_setup = penwell_arch_setup,
-};
-
-static void mfld_power_off(void)
-{
-}
-
 static unsigned long __init mfld_calibrate_tsc(void)
 {
        unsigned long fast_calibrate;
@@ -63,9 +53,12 @@ static unsigned long __init mfld_calibrate_tsc(void)
 static void __init penwell_arch_setup(void)
 {
        x86_platform.calibrate_tsc = mfld_calibrate_tsc;
-       pm_power_off = mfld_power_off;
 }
 
+static struct intel_mid_ops penwell_ops = {
+       .arch_setup = penwell_arch_setup,
+};
+
 void *get_penwell_ops(void)
 {
        return &penwell_ops;
index 5eec5e08417f6ff1989e3e2a07b31c62901953d5..e75878f8b14af8f852d814717c3900759b0ed6fc 100644 (file)
@@ -376,10 +376,14 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
        bio_list_init(&punt);
        bio_list_init(&nopunt);
 
-       while ((bio = bio_list_pop(current->bio_list)))
+       while ((bio = bio_list_pop(&current->bio_list[0])))
                bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
+       current->bio_list[0] = nopunt;
 
-       *current->bio_list = nopunt;
+       bio_list_init(&nopunt);
+       while ((bio = bio_list_pop(&current->bio_list[1])))
+               bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
+       current->bio_list[1] = nopunt;
 
        spin_lock(&bs->rescue_lock);
        bio_list_merge(&bs->rescue_list, &punt);
@@ -466,7 +470,9 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
                 * we retry with the original gfp_flags.
                 */
 
-               if (current->bio_list && !bio_list_empty(current->bio_list))
+               if (current->bio_list &&
+                   (!bio_list_empty(&current->bio_list[0]) ||
+                    !bio_list_empty(&current->bio_list[1])))
                        gfp_mask &= ~__GFP_DIRECT_RECLAIM;
 
                p = mempool_alloc(bs->bio_pool, gfp_mask);
index 0eeb99ef654f4ad6874cf579883a263c9894ca31..d772c221cc178bf3ecfe448f3367121ec1d077de 100644 (file)
@@ -1973,7 +1973,14 @@ end_io:
  */
 blk_qc_t generic_make_request(struct bio *bio)
 {
-       struct bio_list bio_list_on_stack;
+       /*
+        * bio_list_on_stack[0] contains bios submitted by the current
+        * make_request_fn.
+        * bio_list_on_stack[1] contains bios that were submitted before
+        * the current make_request_fn, but that haven't been processed
+        * yet.
+        */
+       struct bio_list bio_list_on_stack[2];
        blk_qc_t ret = BLK_QC_T_NONE;
 
        if (!generic_make_request_checks(bio))
@@ -1990,7 +1997,7 @@ blk_qc_t generic_make_request(struct bio *bio)
         * should be added at the tail
         */
        if (current->bio_list) {
-               bio_list_add(current->bio_list, bio);
+               bio_list_add(&current->bio_list[0], bio);
                goto out;
        }
 
@@ -2009,18 +2016,17 @@ blk_qc_t generic_make_request(struct bio *bio)
         * bio_list, and call into ->make_request() again.
         */
        BUG_ON(bio->bi_next);
-       bio_list_init(&bio_list_on_stack);
-       current->bio_list = &bio_list_on_stack;
+       bio_list_init(&bio_list_on_stack[0]);
+       current->bio_list = bio_list_on_stack;
        do {
                struct request_queue *q = bdev_get_queue(bio->bi_bdev);
 
                if (likely(blk_queue_enter(q, false) == 0)) {
-                       struct bio_list hold;
                        struct bio_list lower, same;
 
                        /* Create a fresh bio_list for all subordinate requests */
-                       hold = bio_list_on_stack;
-                       bio_list_init(&bio_list_on_stack);
+                       bio_list_on_stack[1] = bio_list_on_stack[0];
+                       bio_list_init(&bio_list_on_stack[0]);
                        ret = q->make_request_fn(q, bio);
 
                        blk_queue_exit(q);
@@ -2030,19 +2036,19 @@ blk_qc_t generic_make_request(struct bio *bio)
                         */
                        bio_list_init(&lower);
                        bio_list_init(&same);
-                       while ((bio = bio_list_pop(&bio_list_on_stack)) != NULL)
+                       while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
                                if (q == bdev_get_queue(bio->bi_bdev))
                                        bio_list_add(&same, bio);
                                else
                                        bio_list_add(&lower, bio);
                        /* now assemble so we handle the lowest level first */
-                       bio_list_merge(&bio_list_on_stack, &lower);
-                       bio_list_merge(&bio_list_on_stack, &same);
-                       bio_list_merge(&bio_list_on_stack, &hold);
+                       bio_list_merge(&bio_list_on_stack[0], &lower);
+                       bio_list_merge(&bio_list_on_stack[0], &same);
+                       bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
                } else {
                        bio_io_error(bio);
                }
-               bio = bio_list_pop(current->bio_list);
+               bio = bio_list_pop(&bio_list_on_stack[0]);
        } while (bio);
        current->bio_list = NULL; /* deactivate */
 
index e48bc2c72615de016f013a2e98ea72cd49713a04..9d97bfc4d4657b586d1a9b4d077a8e673300d79a 100644 (file)
@@ -295,6 +295,9 @@ int blk_mq_reinit_tagset(struct blk_mq_tag_set *set)
        for (i = 0; i < set->nr_hw_queues; i++) {
                struct blk_mq_tags *tags = set->tags[i];
 
+               if (!tags)
+                       continue;
+
                for (j = 0; j < tags->nr_tags; j++) {
                        if (!tags->static_rqs[j])
                                continue;
index 159187a28d66521b4ab0109d3db38e6225ac71b3..08a49c69738bb5287530985c7294639b706ad25a 100644 (file)
@@ -697,17 +697,8 @@ static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
 {
        struct blk_mq_timeout_data *data = priv;
 
-       if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) {
-               /*
-                * If a request wasn't started before the queue was
-                * marked dying, kill it here or it'll go unnoticed.
-                */
-               if (unlikely(blk_queue_dying(rq->q))) {
-                       rq->errors = -EIO;
-                       blk_mq_end_request(rq, rq->errors);
-               }
+       if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags))
                return;
-       }
 
        if (time_after_eq(jiffies, rq->deadline)) {
                if (!blk_mark_rq_complete(rq))
@@ -1434,7 +1425,8 @@ static blk_qc_t request_to_qc_t(struct blk_mq_hw_ctx *hctx, struct request *rq)
        return blk_tag_to_qc_t(rq->internal_tag, hctx->queue_num, true);
 }
 
-static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie)
+static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie,
+                                     bool may_sleep)
 {
        struct request_queue *q = rq->q;
        struct blk_mq_queue_data bd = {
@@ -1475,7 +1467,7 @@ static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie)
        }
 
 insert:
-       blk_mq_sched_insert_request(rq, false, true, true, false);
+       blk_mq_sched_insert_request(rq, false, true, false, may_sleep);
 }
 
 /*
@@ -1569,11 +1561,11 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
                if (!(data.hctx->flags & BLK_MQ_F_BLOCKING)) {
                        rcu_read_lock();
-                       blk_mq_try_issue_directly(old_rq, &cookie);
+                       blk_mq_try_issue_directly(old_rq, &cookie, false);
                        rcu_read_unlock();
                } else {
                        srcu_idx = srcu_read_lock(&data.hctx->queue_rq_srcu);
-                       blk_mq_try_issue_directly(old_rq, &cookie);
+                       blk_mq_try_issue_directly(old_rq, &cookie, true);
                        srcu_read_unlock(&data.hctx->queue_rq_srcu, srcu_idx);
                }
                goto done;
index 9b43efb8933fb9a0f352922029b86903e5b7c8e7..186fcb981e9b1d9696e3e000b0fde7b86e1a9663 100644 (file)
@@ -30,11 +30,11 @@ static void blk_stat_flush_batch(struct blk_rq_stat *stat)
 
 static void blk_stat_sum(struct blk_rq_stat *dst, struct blk_rq_stat *src)
 {
+       blk_stat_flush_batch(src);
+
        if (!src->nr_samples)
                return;
 
-       blk_stat_flush_batch(src);
-
        dst->min = min(dst->min, src->min);
        dst->max = max(dst->max, src->max);
 
index f5e18c2a48527bb3f5bbdc5202b37577689710b3..690deca17c35287c00171466f7b06e53262b0601 100644 (file)
@@ -266,7 +266,7 @@ unlock:
        return err;
 }
 
-int af_alg_accept(struct sock *sk, struct socket *newsock)
+int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
 {
        struct alg_sock *ask = alg_sk(sk);
        const struct af_alg_type *type;
@@ -281,7 +281,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
        if (!type)
                goto unlock;
 
-       sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, 0);
+       sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, kern);
        err = -ENOMEM;
        if (!sk2)
                goto unlock;
@@ -323,9 +323,10 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(af_alg_accept);
 
-static int alg_accept(struct socket *sock, struct socket *newsock, int flags)
+static int alg_accept(struct socket *sock, struct socket *newsock, int flags,
+                     bool kern)
 {
-       return af_alg_accept(sock->sk, newsock);
+       return af_alg_accept(sock->sk, newsock, kern);
 }
 
 static const struct proto_ops alg_proto_ops = {
index 54fc90e8339ce83edab95908adb16ddc1e9d7d32..5e92bd275ef38e8dfe47d9ca50a0e5ced51b2d0e 100644 (file)
@@ -239,7 +239,8 @@ unlock:
        return err ?: len;
 }
 
-static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
+static int hash_accept(struct socket *sock, struct socket *newsock, int flags,
+                      bool kern)
 {
        struct sock *sk = sock->sk;
        struct alg_sock *ask = alg_sk(sk);
@@ -260,7 +261,7 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
        if (err)
                return err;
 
-       err = af_alg_accept(ask->parent, newsock);
+       err = af_alg_accept(ask->parent, newsock, kern);
        if (err)
                return err;
 
@@ -378,7 +379,7 @@ static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
 }
 
 static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
-                            int flags)
+                            int flags, bool kern)
 {
        int err;
 
@@ -386,7 +387,7 @@ static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
        if (err)
                return err;
 
-       return hash_accept(sock, newsock, flags);
+       return hash_accept(sock, newsock, flags, kern);
 }
 
 static struct proto_ops algif_hash_ops_nokey = {
index 4467a8089ab890695ccf7072220d9c43d1f29c2d..0143135b3abe3749d8a3bab492eb67b2e63a5d01 100644 (file)
@@ -182,11 +182,6 @@ int __weak arch_register_cpu(int cpu)
 
 void __weak arch_unregister_cpu(int cpu) {}
 
-int __weak acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
-{
-       return -ENODEV;
-}
-
 static int acpi_processor_hotadd_init(struct acpi_processor *pr)
 {
        unsigned long long sta;
@@ -285,6 +280,13 @@ static int acpi_processor_get_info(struct acpi_device *device)
                pr->acpi_id = value;
        }
 
+       if (acpi_duplicate_processor_id(pr->acpi_id)) {
+               dev_err(&device->dev,
+                       "Failed to get unique processor _UID (0x%x)\n",
+                       pr->acpi_id);
+               return -ENODEV;
+       }
+
        pr->phys_id = acpi_get_phys_id(pr->handle, device_declaration,
                                        pr->acpi_id);
        if (invalid_phys_cpuid(pr->phys_id))
@@ -585,7 +587,7 @@ static struct acpi_scan_handler processor_container_handler = {
 static int nr_unique_ids __initdata;
 
 /* The number of the duplicate processor IDs */
-static int nr_duplicate_ids __initdata;
+static int nr_duplicate_ids;
 
 /* Used to store the unique processor IDs */
 static int unique_processor_ids[] __initdata = {
@@ -593,7 +595,7 @@ static int unique_processor_ids[] __initdata = {
 };
 
 /* Used to store the duplicate processor IDs */
-static int duplicate_processor_ids[] __initdata = {
+static int duplicate_processor_ids[] = {
        [0 ... NR_CPUS - 1] = -1,
 };
 
@@ -638,28 +640,53 @@ static acpi_status __init acpi_processor_ids_walk(acpi_handle handle,
                                                  void **rv)
 {
        acpi_status status;
+       acpi_object_type acpi_type;
+       unsigned long long uid;
        union acpi_object object = { 0 };
        struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
 
-       status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
+       status = acpi_get_type(handle, &acpi_type);
        if (ACPI_FAILURE(status))
-               acpi_handle_info(handle, "Not get the processor object\n");
-       else
-               processor_validated_ids_update(object.processor.proc_id);
+               return false;
+
+       switch (acpi_type) {
+       case ACPI_TYPE_PROCESSOR:
+               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
+               if (ACPI_FAILURE(status))
+                       goto err;
+               uid = object.processor.proc_id;
+               break;
+
+       case ACPI_TYPE_DEVICE:
+               status = acpi_evaluate_integer(handle, "_UID", NULL, &uid);
+               if (ACPI_FAILURE(status))
+                       goto err;
+               break;
+       default:
+               goto err;
+       }
+
+       processor_validated_ids_update(uid);
+       return true;
+
+err:
+       acpi_handle_info(handle, "Invalid processor object\n");
+       return false;
 
-       return AE_OK;
 }
 
-static void __init acpi_processor_check_duplicates(void)
+void __init acpi_processor_check_duplicates(void)
 {
-       /* Search all processor nodes in ACPI namespace */
+       /* check the correctness for all processors in ACPI namespace */
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
                                                ACPI_UINT32_MAX,
                                                acpi_processor_ids_walk,
                                                NULL, NULL, NULL);
+       acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_ids_walk,
+                                               NULL, NULL);
 }
 
-bool __init acpi_processor_validate_proc_id(int proc_id)
+bool acpi_duplicate_processor_id(int proc_id)
 {
        int i;
 
index 80cb5eb75b633db8aa278b5e709cfddd697f9a7e..34fbe027e73a26f195f981d2fbd373608f724415 100644 (file)
@@ -1249,7 +1249,6 @@ static int __init acpi_init(void)
        acpi_wakeup_device_init();
        acpi_debugger_init();
        acpi_setup_sb_notify_handler();
-       acpi_set_processor_mapping();
        return 0;
 }
 
index 611a5585a9024a728c71e60ada951b3a73936708..b933061b6b607c467e20317412c63c78728396fc 100644 (file)
@@ -32,12 +32,12 @@ static struct acpi_table_madt *get_madt_table(void)
 }
 
 static int map_lapic_id(struct acpi_subtable_header *entry,
-                u32 acpi_id, phys_cpuid_t *apic_id, bool ignore_disabled)
+                u32 acpi_id, phys_cpuid_t *apic_id)
 {
        struct acpi_madt_local_apic *lapic =
                container_of(entry, struct acpi_madt_local_apic, header);
 
-       if (ignore_disabled && !(lapic->lapic_flags & ACPI_MADT_ENABLED))
+       if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
                return -ENODEV;
 
        if (lapic->processor_id != acpi_id)
@@ -48,13 +48,12 @@ static int map_lapic_id(struct acpi_subtable_header *entry,
 }
 
 static int map_x2apic_id(struct acpi_subtable_header *entry,
-               int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id,
-               bool ignore_disabled)
+               int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id)
 {
        struct acpi_madt_local_x2apic *apic =
                container_of(entry, struct acpi_madt_local_x2apic, header);
 
-       if (ignore_disabled && !(apic->lapic_flags & ACPI_MADT_ENABLED))
+       if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
                return -ENODEV;
 
        if (device_declaration && (apic->uid == acpi_id)) {
@@ -66,13 +65,12 @@ static int map_x2apic_id(struct acpi_subtable_header *entry,
 }
 
 static int map_lsapic_id(struct acpi_subtable_header *entry,
-               int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id,
-               bool ignore_disabled)
+               int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id)
 {
        struct acpi_madt_local_sapic *lsapic =
                container_of(entry, struct acpi_madt_local_sapic, header);
 
-       if (ignore_disabled && !(lsapic->lapic_flags & ACPI_MADT_ENABLED))
+       if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
                return -ENODEV;
 
        if (device_declaration) {
@@ -89,13 +87,12 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
  * Retrieve the ARM CPU physical identifier (MPIDR)
  */
 static int map_gicc_mpidr(struct acpi_subtable_header *entry,
-               int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr,
-               bool ignore_disabled)
+               int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr)
 {
        struct acpi_madt_generic_interrupt *gicc =
            container_of(entry, struct acpi_madt_generic_interrupt, header);
 
-       if (ignore_disabled && !(gicc->flags & ACPI_MADT_ENABLED))
+       if (!(gicc->flags & ACPI_MADT_ENABLED))
                return -ENODEV;
 
        /* device_declaration means Device object in DSDT, in the
@@ -112,7 +109,7 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
 }
 
 static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
-                                  int type, u32 acpi_id, bool ignore_disabled)
+                                  int type, u32 acpi_id)
 {
        unsigned long madt_end, entry;
        phys_cpuid_t phys_id = PHYS_CPUID_INVALID;      /* CPU hardware ID */
@@ -130,20 +127,16 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
                struct acpi_subtable_header *header =
                        (struct acpi_subtable_header *)entry;
                if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
-                       if (!map_lapic_id(header, acpi_id, &phys_id,
-                                         ignore_disabled))
+                       if (!map_lapic_id(header, acpi_id, &phys_id))
                                break;
                } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
-                       if (!map_x2apic_id(header, type, acpi_id, &phys_id,
-                                          ignore_disabled))
+                       if (!map_x2apic_id(header, type, acpi_id, &phys_id))
                                break;
                } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
-                       if (!map_lsapic_id(header, type, acpi_id, &phys_id,
-                                          ignore_disabled))
+                       if (!map_lsapic_id(header, type, acpi_id, &phys_id))
                                break;
                } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
-                       if (!map_gicc_mpidr(header, type, acpi_id, &phys_id,
-                                           ignore_disabled))
+                       if (!map_gicc_mpidr(header, type, acpi_id, &phys_id))
                                break;
                }
                entry += header->length;
@@ -161,15 +154,14 @@ phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
        if (!madt)
                return PHYS_CPUID_INVALID;
 
-       rv = map_madt_entry(madt, 1, acpi_id, true);
+       rv = map_madt_entry(madt, 1, acpi_id);
 
        acpi_put_table((struct acpi_table_header *)madt);
 
        return rv;
 }
 
-static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id,
-                                 bool ignore_disabled)
+static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
@@ -190,38 +182,30 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id,
 
        header = (struct acpi_subtable_header *)obj->buffer.pointer;
        if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
-               map_lapic_id(header, acpi_id, &phys_id, ignore_disabled);
+               map_lapic_id(header, acpi_id, &phys_id);
        else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
-               map_lsapic_id(header, type, acpi_id, &phys_id, ignore_disabled);
+               map_lsapic_id(header, type, acpi_id, &phys_id);
        else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
-               map_x2apic_id(header, type, acpi_id, &phys_id, ignore_disabled);
+               map_x2apic_id(header, type, acpi_id, &phys_id);
        else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
-               map_gicc_mpidr(header, type, acpi_id, &phys_id,
-                              ignore_disabled);
+               map_gicc_mpidr(header, type, acpi_id, &phys_id);
 
 exit:
        kfree(buffer.pointer);
        return phys_id;
 }
 
-static phys_cpuid_t __acpi_get_phys_id(acpi_handle handle, int type,
-                                      u32 acpi_id, bool ignore_disabled)
+phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
 {
        phys_cpuid_t phys_id;
 
-       phys_id = map_mat_entry(handle, type, acpi_id, ignore_disabled);
+       phys_id = map_mat_entry(handle, type, acpi_id);
        if (invalid_phys_cpuid(phys_id))
-               phys_id = map_madt_entry(get_madt_table(), type, acpi_id,
-                                          ignore_disabled);
+               phys_id = map_madt_entry(get_madt_table(), type, acpi_id);
 
        return phys_id;
 }
 
-phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
-{
-       return __acpi_get_phys_id(handle, type, acpi_id, true);
-}
-
 int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id)
 {
 #ifdef CONFIG_SMP
@@ -278,79 +262,6 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 }
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
 
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-static bool __init
-map_processor(acpi_handle handle, phys_cpuid_t *phys_id, int *cpuid)
-{
-       int type, id;
-       u32 acpi_id;
-       acpi_status status;
-       acpi_object_type acpi_type;
-       unsigned long long tmp;
-       union acpi_object object = { 0 };
-       struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-
-       status = acpi_get_type(handle, &acpi_type);
-       if (ACPI_FAILURE(status))
-               return false;
-
-       switch (acpi_type) {
-       case ACPI_TYPE_PROCESSOR:
-               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
-               if (ACPI_FAILURE(status))
-                       return false;
-               acpi_id = object.processor.proc_id;
-
-               /* validate the acpi_id */
-               if(acpi_processor_validate_proc_id(acpi_id))
-                       return false;
-               break;
-       case ACPI_TYPE_DEVICE:
-               status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
-               if (ACPI_FAILURE(status))
-                       return false;
-               acpi_id = tmp;
-               break;
-       default:
-               return false;
-       }
-
-       type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
-
-       *phys_id = __acpi_get_phys_id(handle, type, acpi_id, false);
-       id = acpi_map_cpuid(*phys_id, acpi_id);
-
-       if (id < 0)
-               return false;
-       *cpuid = id;
-       return true;
-}
-
-static acpi_status __init
-set_processor_node_mapping(acpi_handle handle, u32 lvl, void *context,
-                          void **rv)
-{
-       phys_cpuid_t phys_id;
-       int cpu_id;
-
-       if (!map_processor(handle, &phys_id, &cpu_id))
-               return AE_ERROR;
-
-       acpi_map_cpu2node(handle, cpu_id, phys_id);
-       return AE_OK;
-}
-
-void __init acpi_set_processor_mapping(void)
-{
-       /* Set persistent cpu <-> node mapping for all processors. */
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX, set_processor_node_mapping,
-                           NULL, NULL, NULL);
-}
-#else
-void __init acpi_set_processor_mapping(void) {}
-#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-
 #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
 static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base,
                         u64 *phys_addr, int *ioapic_id)
index 01c94669a2b0ad91976daf9f3c7ef3338b48e965..3afa8c1fa12702c251d5d3654e2026ba0ebfcd62 100644 (file)
@@ -30,7 +30,7 @@ static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
                return true;
 
        if (!memcmp(h->oem_table_id, "QDF2400 ", ACPI_OEM_TABLE_ID_SIZE) &&
-                       h->oem_revision == 0)
+                       h->oem_revision == 1)
                return true;
 
        return false;
index 85d833289f28f85de9aa98efe52a05a921cdc3bd..4c96f3ac4976d9bbc306010ca4fd76bb7d33015e 100644 (file)
@@ -177,7 +177,8 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
        case AHCI_LS1043A:
                if (!qpriv->ecc_addr)
                        return -EINVAL;
-               writel(ECC_DIS_ARMV8_CH2, qpriv->ecc_addr);
+               writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
+                               qpriv->ecc_addr);
                writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
                writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
                if (qpriv->is_dmacoherent)
@@ -194,7 +195,8 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
        case AHCI_LS1046A:
                if (!qpriv->ecc_addr)
                        return -EINVAL;
-               writel(ECC_DIS_ARMV8_CH2, qpriv->ecc_addr);
+               writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
+                               qpriv->ecc_addr);
                writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
                writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
                if (qpriv->is_dmacoherent)
index 2bd92dca3e6204027f6c1b5fb07ba519cbe039fa..274d6d7193d7caa9b57f111962aa6e245ebc8f7c 100644 (file)
@@ -1482,7 +1482,6 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                break;
 
        default:
-               WARN_ON_ONCE(1);
                return AC_ERR_SYSTEM;
        }
 
index 46698232e6bff069293200a5da842e196a4a0730..19e6e539a061b93a6ac81975a69b3cdba7b1d699 100644 (file)
@@ -224,7 +224,6 @@ static DECLARE_TRANSPORT_CLASS(ata_port_class,
 
 static void ata_tport_release(struct device *dev)
 {
-       put_device(dev->parent);
 }
 
 /**
@@ -284,7 +283,7 @@ int ata_tport_add(struct device *parent,
        device_initialize(dev);
        dev->type = &ata_port_type;
 
-       dev->parent = get_device(parent);
+       dev->parent = parent;
        dev->release = ata_tport_release;
        dev_set_name(dev, "ata%d", ap->print_id);
        transport_setup_device(dev);
@@ -348,7 +347,6 @@ static DECLARE_TRANSPORT_CLASS(ata_link_class,
 
 static void ata_tlink_release(struct device *dev)
 {
-       put_device(dev->parent);
 }
 
 /**
@@ -410,7 +408,7 @@ int ata_tlink_add(struct ata_link *link)
        int error;
 
        device_initialize(dev);
-       dev->parent = get_device(&ap->tdev);
+       dev->parent = &ap->tdev;
        dev->release = ata_tlink_release;
        if (ata_is_host_link(link))
                dev_set_name(dev, "link%d", ap->print_id);
@@ -589,7 +587,6 @@ static DECLARE_TRANSPORT_CLASS(ata_dev_class,
 
 static void ata_tdev_release(struct device *dev)
 {
-       put_device(dev->parent);
 }
 
 /**
@@ -662,7 +659,7 @@ static int ata_tdev_add(struct ata_device *ata_dev)
        int error;
 
        device_initialize(dev);
-       dev->parent = get_device(&link->tdev);
+       dev->parent = &link->tdev;
        dev->release = ata_tdev_release;
        if (ata_is_host_link(link))
                dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
index 684bda4d14a187b41ff453bf33ad8df4774c977f..6bb60fb6a30b7b9b4fd42e2872261317b38c22b5 100644 (file)
@@ -639,11 +639,6 @@ int lock_device_hotplug_sysfs(void)
        return restart_syscall();
 }
 
-void assert_held_device_hotplug(void)
-{
-       lockdep_assert_held(&device_hotplug_lock);
-}
-
 #ifdef CONFIG_BLOCK
 static inline int device_is_not_partition(struct device *dev)
 {
index c2c14a12713b56038c8c21deae2212550d24422b..08e054507d0bcd7fc59f5d14d0927ba6ca35291f 100644 (file)
@@ -344,7 +344,8 @@ config BT_WILINK
 
 config BT_QCOMSMD
        tristate "Qualcomm SMD based HCI support"
-       depends on (QCOM_SMD && QCOM_WCNSS_CTRL) || COMPILE_TEST
+       depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
+       depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n)
        select BT_QCA
        help
          Qualcomm SMD based HCI driver.
index 4a99ac756f0815a890665f1433b1038a98069be9..9959c762da2f8ec1f5cb0fde48021598f3deecfd 100644 (file)
@@ -55,6 +55,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 struct amd768_priv {
        void __iomem *iobase;
        struct pci_dev *pcidev;
+       u32 pmbase;
 };
 
 static int amd_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
@@ -148,33 +149,58 @@ found:
        if (pmbase == 0)
                return -EIO;
 
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       if (!devm_request_region(&pdev->dev, pmbase + PMBASE_OFFSET,
-                               PMBASE_SIZE, DRV_NAME)) {
+       if (!request_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE, DRV_NAME)) {
                dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n",
                        pmbase + 0xF0);
-               return -EBUSY;
+               err = -EBUSY;
+               goto out;
        }
 
-       priv->iobase = devm_ioport_map(&pdev->dev, pmbase + PMBASE_OFFSET,
-                       PMBASE_SIZE);
+       priv->iobase = ioport_map(pmbase + PMBASE_OFFSET, PMBASE_SIZE);
        if (!priv->iobase) {
                pr_err(DRV_NAME "Cannot map ioport\n");
-               return -ENOMEM;
+               err = -EINVAL;
+               goto err_iomap;
        }
 
        amd_rng.priv = (unsigned long)priv;
+       priv->pmbase = pmbase;
        priv->pcidev = pdev;
 
        pr_info(DRV_NAME " detected\n");
-       return devm_hwrng_register(&pdev->dev, &amd_rng);
+       err = hwrng_register(&amd_rng);
+       if (err) {
+               pr_err(DRV_NAME " registering failed (%d)\n", err);
+               goto err_hwrng;
+       }
+       return 0;
+
+err_hwrng:
+       ioport_unmap(priv->iobase);
+err_iomap:
+       release_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE);
+out:
+       kfree(priv);
+       return err;
 }
 
 static void __exit mod_exit(void)
 {
+       struct amd768_priv *priv;
+
+       priv = (struct amd768_priv *)amd_rng.priv;
+
+       hwrng_unregister(&amd_rng);
+
+       ioport_unmap(priv->iobase);
+
+       release_region(priv->pmbase + PMBASE_OFFSET, PMBASE_SIZE);
+
+       kfree(priv);
 }
 
 module_init(mod_init);
index e7a2459420291b6b931b285fe2b9be22cdd3e897..e1d421a36a138d6a5e30b16bf62208846b5372ab 100644 (file)
@@ -31,6 +31,9 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 
+
+#define PFX    KBUILD_MODNAME ": "
+
 #define GEODE_RNG_DATA_REG   0x50
 #define GEODE_RNG_STATUS_REG 0x54
 
@@ -82,6 +85,7 @@ static struct hwrng geode_rng = {
 
 static int __init mod_init(void)
 {
+       int err = -ENODEV;
        struct pci_dev *pdev = NULL;
        const struct pci_device_id *ent;
        void __iomem *mem;
@@ -89,27 +93,43 @@ static int __init mod_init(void)
 
        for_each_pci_dev(pdev) {
                ent = pci_match_id(pci_tbl, pdev);
-               if (ent) {
-                       rng_base = pci_resource_start(pdev, 0);
-                       if (rng_base == 0)
-                               return -ENODEV;
-
-                       mem = devm_ioremap(&pdev->dev, rng_base, 0x58);
-                       if (!mem)
-                               return -ENOMEM;
-                       geode_rng.priv = (unsigned long)mem;
-
-                       pr_info("AMD Geode RNG detected\n");
-                       return devm_hwrng_register(&pdev->dev, &geode_rng);
-               }
+               if (ent)
+                       goto found;
        }
-
        /* Device not found. */
-       return -ENODEV;
+       goto out;
+
+found:
+       rng_base = pci_resource_start(pdev, 0);
+       if (rng_base == 0)
+               goto out;
+       err = -ENOMEM;
+       mem = ioremap(rng_base, 0x58);
+       if (!mem)
+               goto out;
+       geode_rng.priv = (unsigned long)mem;
+
+       pr_info("AMD Geode RNG detected\n");
+       err = hwrng_register(&geode_rng);
+       if (err) {
+               pr_err(PFX "RNG registering failed (%d)\n",
+                      err);
+               goto err_unmap;
+       }
+out:
+       return err;
+
+err_unmap:
+       iounmap(mem);
+       goto out;
 }
 
 static void __exit mod_exit(void)
 {
+       void __iomem *mem = (void __iomem *)geode_rng.priv;
+
+       hwrng_unregister(&geode_rng);
+       iounmap(mem);
 }
 
 module_init(mod_init);
index 3ad86fdf954e96a71b16f436f2b22bd02e6cbd8f..b1ad12552b566a6892a7de411e9cd0c65cf25933 100644 (file)
@@ -397,9 +397,8 @@ static int of_get_omap_rng_device_details(struct omap_rng_dev *priv,
                                irq, err);
                        return err;
                }
-               omap_rng_write(priv, RNG_INTMASK_REG, RNG_SHUTDOWN_OFLO_MASK);
 
-               priv->clk = of_clk_get(pdev->dev.of_node, 0);
+               priv->clk = devm_clk_get(&pdev->dev, NULL);
                if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
                        return -EPROBE_DEFER;
                if (!IS_ERR(priv->clk)) {
@@ -408,6 +407,19 @@ static int of_get_omap_rng_device_details(struct omap_rng_dev *priv,
                                dev_err(&pdev->dev, "unable to enable the clk, "
                                                    "err = %d\n", err);
                }
+
+               /*
+                * On OMAP4, enabling the shutdown_oflo interrupt is
+                * done in the interrupt mask register. There is no
+                * such register on EIP76, and it's enabled by the
+                * same bit in the control register
+                */
+               if (priv->pdata->regs[RNG_INTMASK_REG])
+                       omap_rng_write(priv, RNG_INTMASK_REG,
+                                      RNG_SHUTDOWN_OFLO_MASK);
+               else
+                       omap_rng_write(priv, RNG_CONTROL_REG,
+                                      RNG_SHUTDOWN_OFLO_MASK);
        }
        return 0;
 }
index 0fb39fe217d17ae1bb681912764b2506007f5f42..67201f67a14af7b07aec557308a7fb39d1432157 100644 (file)
@@ -2502,7 +2502,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
 
        clk->core = hw->core;
        clk->dev_id = dev_id;
-       clk->con_id = con_id;
+       clk->con_id = kstrdup_const(con_id, GFP_KERNEL);
        clk->max_rate = ULONG_MAX;
 
        clk_prepare_lock();
@@ -2518,6 +2518,7 @@ void __clk_free_clk(struct clk *clk)
        hlist_del(&clk->clks_node);
        clk_prepare_unlock();
 
+       kfree_const(clk->con_id);
        kfree(clk);
 }
 
index 924f560dcf80e8a5681fba4c670524b2b20b01ee..00d4150e33c37434c056ba27867db908d6117bdf 100644 (file)
@@ -127,7 +127,7 @@ PNAME(mux_ddrphy_p)         = { "dpll_ddr", "gpll_ddr" };
 PNAME(mux_pll_src_3plls_p)     = { "apll", "dpll", "gpll" };
 PNAME(mux_timer_p)             = { "xin24m", "pclk_peri_src" };
 
-PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p)    = { "apll", "dpll", "gpll" "usb480m" };
+PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p)    = { "apll", "dpll", "gpll", "usb480m" };
 
 PNAME(mux_mmc_src_p)   = { "apll", "dpll", "gpll", "xin24m" };
 PNAME(mux_i2s_pre_p)   = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
@@ -450,6 +450,13 @@ static void __init rk3036_clk_init(struct device_node *np)
                return;
        }
 
+       /*
+        * Make uart_pll_clk a child of the gpll, as all other sources are
+        * not that usable / stable.
+        */
+       writel_relaxed(HIWORD_UPDATE(0x2, 0x3, 10),
+                      reg_base + RK2928_CLKSEL_CON(13));
+
        ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
        if (IS_ERR(ctx)) {
                pr_err("%s: rockchip clk init failed\n", __func__);
index 695bbf9ef428f98f5348d100a6af2525f04afb59..72109d2cf41b29da83dd88dbdb0e820364c893dd 100644 (file)
@@ -80,6 +80,7 @@ config SUN6I_A31_CCU
        select SUNXI_CCU_DIV
        select SUNXI_CCU_NK
        select SUNXI_CCU_NKM
+       select SUNXI_CCU_NKMP
        select SUNXI_CCU_NM
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
index e3c084cc6da55e77f24bf058038bda710fd792d0..f54114c607df76edeb77c70e0f7c97656e67634c 100644 (file)
@@ -566,7 +566,7 @@ static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
                             0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
 
 /* Fixed Factor clocks */
-static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0);
+static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0);
 
 /* We hardcode the divider to 4 for now */
 static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
index 4c9a920ff4ab7c351d59333d131d039f5e36f40a..89e68d29bf456ab3d682f7d2ba7d35ad4a21bb58 100644 (file)
@@ -608,7 +608,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", lcd_ch1_parents,
                                 0x150, 0, 4, 24, 2, BIT(31),
                                 CLK_SET_RATE_PARENT);
 
-static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", 0x150, BIT(31), 0);
+static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", 0x150, BIT(30), 0);
 
 static SUNXI_CCU_GATE(ps_clk, "ps", "lcd1-ch1", 0x140, BIT(31), 0);
 
index 22c2ca7a2a221c1f25456e6e2548d381fbc23adf..b583f186a804df669e974f811e6bef91c4aaa877 100644 (file)
@@ -85,6 +85,10 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
        unsigned int m, p;
        u32 reg;
 
+       /* Adjust parent_rate according to pre-dividers */
+       ccu_mux_helper_adjust_parent_for_prediv(&cmp->common, &cmp->mux,
+                                               -1, &parent_rate);
+
        reg = readl(cmp->common.base + cmp->common.reg);
 
        m = reg >> cmp->m.shift;
@@ -117,6 +121,10 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned int m, p;
        u32 reg;
 
+       /* Adjust parent_rate according to pre-dividers */
+       ccu_mux_helper_adjust_parent_for_prediv(&cmp->common, &cmp->mux,
+                                               -1, &parent_rate);
+
        max_m = cmp->m.max ?: 1 << cmp->m.width;
        max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
 
index a2b40a0001577d2579aa563341d1d890797f4b7f..488055ed944f2b9dff8ca1baa5059ea22879328b 100644 (file)
@@ -107,7 +107,7 @@ static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw,
        p = reg >> nkmp->p.shift;
        p &= (1 << nkmp->p.width) - 1;
 
-       return parent_rate * n * k >> p / m;
+       return (parent_rate * n * k >> p) / m;
 }
 
 static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
index 745844ee973e1deda08203725d9b9d1b8e412972..d4ca9962a7595a0206710a0dd4a95656f426ae8e 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/atmel_tc.h>
-#include <linux/sched_clock.h>
 
 
 /*
@@ -57,14 +56,9 @@ static u64 tc_get_cycles(struct clocksource *cs)
        return (upper << 16) | lower;
 }
 
-static u32 tc_get_cv32(void)
-{
-       return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
-}
-
 static u64 tc_get_cycles32(struct clocksource *cs)
 {
-       return tc_get_cv32();
+       return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
 }
 
 static struct clocksource clksrc = {
@@ -75,11 +69,6 @@ static struct clocksource clksrc = {
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static u64 notrace tc_read_sched_clock(void)
-{
-       return tc_get_cv32();
-}
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
 struct tc_clkevt_device {
@@ -350,9 +339,6 @@ static int __init tcb_clksrc_init(void)
                clksrc.read = tc_get_cycles32;
                /* setup ony channel 0 */
                tcb_setup_single_chan(tc, best_divisor_idx);
-
-               /* register sched_clock on chips with single 32 bit counter */
-               sched_clock_register(tc_read_sched_clock, 32, divided_rate);
        } else {
                /* tclib will give us three clocks no matter what the
                 * underlying platform supports.
index 38b9fdf854a49a7e4ba9950e365904d18b64caf5..5dbdd261aa736bf0f1af605ea8eb2d8acefe808c 100644 (file)
@@ -680,9 +680,11 @@ static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
                                        char *buf)
 {
        unsigned int cur_freq = __cpufreq_get(policy);
-       if (!cur_freq)
-               return sprintf(buf, "<unknown>");
-       return sprintf(buf, "%u\n", cur_freq);
+
+       if (cur_freq)
+               return sprintf(buf, "%u\n", cur_freq);
+
+       return sprintf(buf, "<unknown>\n");
 }
 
 /**
@@ -1182,6 +1184,9 @@ static int cpufreq_online(unsigned int cpu)
                for_each_cpu(j, policy->related_cpus)
                        per_cpu(cpufreq_cpu_data, j) = policy;
                write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+       } else {
+               policy->min = policy->user_policy.min;
+               policy->max = policy->user_policy.max;
        }
 
        if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
index 3d37219a0dd7afc3108b017f1d2960868efb7903..283491f742d3d78659696bd58c48fc5a3bd7a370 100644 (file)
@@ -84,6 +84,11 @@ static inline u64 div_ext_fp(u64 x, u64 y)
        return div64_u64(x << EXT_FRAC_BITS, y);
 }
 
+static inline int32_t percent_ext_fp(int percent)
+{
+       return div_ext_fp(percent, 100);
+}
+
 /**
  * struct sample -     Store performance sample
  * @core_avg_perf:     Ratio of APERF/MPERF which is the actual average
@@ -359,9 +364,7 @@ static bool driver_registered __read_mostly;
 static bool acpi_ppc;
 #endif
 
-static struct perf_limits performance_limits;
-static struct perf_limits powersave_limits;
-static struct perf_limits *limits;
+static struct perf_limits global;
 
 static void intel_pstate_init_limits(struct perf_limits *limits)
 {
@@ -372,14 +375,6 @@ static void intel_pstate_init_limits(struct perf_limits *limits)
        limits->max_sysfs_pct = 100;
 }
 
-static void intel_pstate_set_performance_limits(struct perf_limits *limits)
-{
-       intel_pstate_init_limits(limits);
-       limits->min_perf_pct = 100;
-       limits->min_perf = int_ext_tofp(1);
-       limits->min_sysfs_pct = 100;
-}
-
 static DEFINE_MUTEX(intel_pstate_driver_lock);
 static DEFINE_MUTEX(intel_pstate_limits_lock);
 
@@ -502,7 +497,7 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
         * correct max turbo frequency based on the turbo state.
         * Also need to convert to MHz as _PSS freq is in MHz.
         */
-       if (!limits->turbo_disabled)
+       if (!global.turbo_disabled)
                cpu->acpi_perf_data.states[0].core_frequency =
                                        policy->cpuinfo.max_freq / 1000;
        cpu->valid_pss_table = true;
@@ -621,7 +616,7 @@ static inline void update_turbo_state(void)
 
        cpu = all_cpu_data[0];
        rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
-       limits->turbo_disabled =
+       global.turbo_disabled =
                (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
                 cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
 }
@@ -845,12 +840,11 @@ static struct freq_attr *hwp_cpufreq_attrs[] = {
 
 static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
 {
-       int min, hw_min, max, hw_max, cpu, range, adj_range;
-       struct perf_limits *perf_limits = limits;
+       int min, hw_min, max, hw_max, cpu;
+       struct perf_limits *perf_limits = &global;
        u64 value, cap;
 
        for_each_cpu(cpu, policy->cpus) {
-               int max_perf_pct, min_perf_pct;
                struct cpudata *cpu_data = all_cpu_data[cpu];
                s16 epp;
 
@@ -859,24 +853,22 @@ static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
 
                rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
                hw_min = HWP_LOWEST_PERF(cap);
-               if (limits->no_turbo)
+               if (global.no_turbo)
                        hw_max = HWP_GUARANTEED_PERF(cap);
                else
                        hw_max = HWP_HIGHEST_PERF(cap);
-               range = hw_max - hw_min;
 
-               max_perf_pct = perf_limits->max_perf_pct;
-               min_perf_pct = perf_limits->min_perf_pct;
+               max = fp_ext_toint(hw_max * perf_limits->max_perf);
+               if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE)
+                       min = max;
+               else
+                       min = fp_ext_toint(hw_max * perf_limits->min_perf);
 
                rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
-               adj_range = min_perf_pct * range / 100;
-               min = hw_min + adj_range;
+
                value &= ~HWP_MIN_PERF(~0L);
                value |= HWP_MIN_PERF(min);
 
-               adj_range = max_perf_pct * range / 100;
-               max = hw_min + adj_range;
-
                value &= ~HWP_MAX_PERF(~0L);
                value |= HWP_MAX_PERF(max);
 
@@ -969,26 +961,18 @@ static int intel_pstate_resume(struct cpufreq_policy *policy)
 }
 
 static void intel_pstate_update_policies(void)
-       __releases(&intel_pstate_limits_lock)
-       __acquires(&intel_pstate_limits_lock)
 {
-       struct perf_limits *saved_limits = limits;
        int cpu;
 
-       mutex_unlock(&intel_pstate_limits_lock);
-
        for_each_possible_cpu(cpu)
                cpufreq_update_policy(cpu);
-
-       mutex_lock(&intel_pstate_limits_lock);
-
-       limits = saved_limits;
 }
 
 /************************** debugfs begin ************************/
 static int pid_param_set(void *data, u64 val)
 {
        *(u32 *)data = val;
+       pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC;
        intel_pstate_reset_all_pid();
        return 0;
 }
@@ -1060,7 +1044,7 @@ static void intel_pstate_debug_hide_params(void)
        static ssize_t show_##file_name                                 \
        (struct kobject *kobj, struct attribute *attr, char *buf)       \
        {                                                               \
-               return sprintf(buf, "%u\n", limits->object);            \
+               return sprintf(buf, "%u\n", global.object);             \
        }
 
 static ssize_t intel_pstate_show_status(char *buf);
@@ -1151,10 +1135,10 @@ static ssize_t show_no_turbo(struct kobject *kobj,
        }
 
        update_turbo_state();
-       if (limits->turbo_disabled)
-               ret = sprintf(buf, "%u\n", limits->turbo_disabled);
+       if (global.turbo_disabled)
+               ret = sprintf(buf, "%u\n", global.turbo_disabled);
        else
-               ret = sprintf(buf, "%u\n", limits->no_turbo);
+               ret = sprintf(buf, "%u\n", global.no_turbo);
 
        mutex_unlock(&intel_pstate_driver_lock);
 
@@ -1181,19 +1165,19 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
        mutex_lock(&intel_pstate_limits_lock);
 
        update_turbo_state();
-       if (limits->turbo_disabled) {
+       if (global.turbo_disabled) {
                pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
                mutex_unlock(&intel_pstate_limits_lock);
                mutex_unlock(&intel_pstate_driver_lock);
                return -EPERM;
        }
 
-       limits->no_turbo = clamp_t(int, input, 0, 1);
-
-       intel_pstate_update_policies();
+       global.no_turbo = clamp_t(int, input, 0, 1);
 
        mutex_unlock(&intel_pstate_limits_lock);
 
+       intel_pstate_update_policies();
+
        mutex_unlock(&intel_pstate_driver_lock);
 
        return count;
@@ -1218,19 +1202,16 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
 
        mutex_lock(&intel_pstate_limits_lock);
 
-       limits->max_sysfs_pct = clamp_t(int, input, 0 , 100);
-       limits->max_perf_pct = min(limits->max_policy_pct,
-                                  limits->max_sysfs_pct);
-       limits->max_perf_pct = max(limits->min_policy_pct,
-                                  limits->max_perf_pct);
-       limits->max_perf_pct = max(limits->min_perf_pct,
-                                  limits->max_perf_pct);
-       limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
-
-       intel_pstate_update_policies();
+       global.max_sysfs_pct = clamp_t(int, input, 0 , 100);
+       global.max_perf_pct = min(global.max_policy_pct, global.max_sysfs_pct);
+       global.max_perf_pct = max(global.min_policy_pct, global.max_perf_pct);
+       global.max_perf_pct = max(global.min_perf_pct, global.max_perf_pct);
+       global.max_perf = percent_ext_fp(global.max_perf_pct);
 
        mutex_unlock(&intel_pstate_limits_lock);
 
+       intel_pstate_update_policies();
+
        mutex_unlock(&intel_pstate_driver_lock);
 
        return count;
@@ -1255,19 +1236,16 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
 
        mutex_lock(&intel_pstate_limits_lock);
 
-       limits->min_sysfs_pct = clamp_t(int, input, 0 , 100);
-       limits->min_perf_pct = max(limits->min_policy_pct,
-                                  limits->min_sysfs_pct);
-       limits->min_perf_pct = min(limits->max_policy_pct,
-                                  limits->min_perf_pct);
-       limits->min_perf_pct = min(limits->max_perf_pct,
-                                  limits->min_perf_pct);
-       limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
-
-       intel_pstate_update_policies();
+       global.min_sysfs_pct = clamp_t(int, input, 0 , 100);
+       global.min_perf_pct = max(global.min_policy_pct, global.min_sysfs_pct);
+       global.min_perf_pct = min(global.max_policy_pct, global.min_perf_pct);
+       global.min_perf_pct = min(global.max_perf_pct, global.min_perf_pct);
+       global.min_perf = percent_ext_fp(global.min_perf_pct);
 
        mutex_unlock(&intel_pstate_limits_lock);
 
+       intel_pstate_update_policies();
+
        mutex_unlock(&intel_pstate_driver_lock);
 
        return count;
@@ -1387,7 +1365,7 @@ static u64 atom_get_val(struct cpudata *cpudata, int pstate)
        u32 vid;
 
        val = (u64)pstate << 8;
-       if (limits->no_turbo && !limits->turbo_disabled)
+       if (global.no_turbo && !global.turbo_disabled)
                val |= (u64)1 << 32;
 
        vid_fp = cpudata->vid.min + mul_fp(
@@ -1557,7 +1535,7 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate)
        u64 val;
 
        val = (u64)pstate << 8;
-       if (limits->no_turbo && !limits->turbo_disabled)
+       if (global.no_turbo && !global.turbo_disabled)
                val |= (u64)1 << 32;
 
        return val;
@@ -1683,9 +1661,9 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
        int max_perf = cpu->pstate.turbo_pstate;
        int max_perf_adj;
        int min_perf;
-       struct perf_limits *perf_limits = limits;
+       struct perf_limits *perf_limits = &global;
 
-       if (limits->no_turbo || limits->turbo_disabled)
+       if (global.no_turbo || global.turbo_disabled)
                max_perf = cpu->pstate.max_pstate;
 
        if (per_cpu_limits)
@@ -1820,7 +1798,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 
        sample->busy_scaled = busy_frac * 100;
 
-       target = limits->no_turbo || limits->turbo_disabled ?
+       target = global.no_turbo || global.turbo_disabled ?
                        cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
        target += target >> 2;
        target = mul_fp(target, busy_frac);
@@ -2080,36 +2058,34 @@ static void intel_pstate_clear_update_util_hook(unsigned int cpu)
 static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
                                            struct perf_limits *limits)
 {
+       int32_t max_policy_perf, min_policy_perf;
 
-       limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,
-                                             policy->cpuinfo.max_freq);
-       limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100);
+       max_policy_perf = div_ext_fp(policy->max, policy->cpuinfo.max_freq);
+       max_policy_perf = clamp_t(int32_t, max_policy_perf, 0, int_ext_tofp(1));
        if (policy->max == policy->min) {
-               limits->min_policy_pct = limits->max_policy_pct;
+               min_policy_perf = max_policy_perf;
        } else {
-               limits->min_policy_pct = DIV_ROUND_UP(policy->min * 100,
-                                                     policy->cpuinfo.max_freq);
-               limits->min_policy_pct = clamp_t(int, limits->min_policy_pct,
-                                                0, 100);
+               min_policy_perf = div_ext_fp(policy->min,
+                                            policy->cpuinfo.max_freq);
+               min_policy_perf = clamp_t(int32_t, min_policy_perf,
+                                         0, max_policy_perf);
        }
 
-       /* Normalize user input to [min_policy_pct, max_policy_pct] */
-       limits->min_perf_pct = max(limits->min_policy_pct,
-                                  limits->min_sysfs_pct);
-       limits->min_perf_pct = min(limits->max_policy_pct,
-                                  limits->min_perf_pct);
-       limits->max_perf_pct = min(limits->max_policy_pct,
-                                  limits->max_sysfs_pct);
-       limits->max_perf_pct = max(limits->min_policy_pct,
-                                  limits->max_perf_pct);
-
-       /* Make sure min_perf_pct <= max_perf_pct */
-       limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
-
-       limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
-       limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
+       /* Normalize user input to [min_perf, max_perf] */
+       limits->min_perf = max(min_policy_perf,
+                              percent_ext_fp(limits->min_sysfs_pct));
+       limits->min_perf = min(limits->min_perf, max_policy_perf);
+       limits->max_perf = min(max_policy_perf,
+                              percent_ext_fp(limits->max_sysfs_pct));
+       limits->max_perf = max(min_policy_perf, limits->max_perf);
+
+       /* Make sure min_perf <= max_perf */
+       limits->min_perf = min(limits->min_perf, limits->max_perf);
+
        limits->max_perf = round_up(limits->max_perf, EXT_FRAC_BITS);
        limits->min_perf = round_up(limits->min_perf, EXT_FRAC_BITS);
+       limits->max_perf_pct = fp_ext_toint(limits->max_perf * 100);
+       limits->min_perf_pct = fp_ext_toint(limits->min_perf * 100);
 
        pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu,
                 limits->max_perf_pct, limits->min_perf_pct);
@@ -2118,7 +2094,7 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 {
        struct cpudata *cpu;
-       struct perf_limits *perf_limits = NULL;
+       struct perf_limits *perf_limits = &global;
 
        if (!policy->cpuinfo.max_freq)
                return -ENODEV;
@@ -2141,21 +2117,6 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 
        mutex_lock(&intel_pstate_limits_lock);
 
-       if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
-               pr_debug("set performance\n");
-               if (!perf_limits) {
-                       limits = &performance_limits;
-                       perf_limits = limits;
-               }
-       } else {
-               pr_debug("set powersave\n");
-               if (!perf_limits) {
-                       limits = &powersave_limits;
-                       perf_limits = limits;
-               }
-
-       }
-
        intel_pstate_update_perf_limits(policy, perf_limits);
 
        if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
@@ -2179,16 +2140,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
 {
        struct cpudata *cpu = all_cpu_data[policy->cpu];
-       struct perf_limits *perf_limits;
-
-       if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
-               perf_limits = &performance_limits;
-       else
-               perf_limits = &powersave_limits;
 
        update_turbo_state();
-       policy->cpuinfo.max_freq = perf_limits->turbo_disabled ||
-                                       perf_limits->no_turbo ?
+       policy->cpuinfo.max_freq = global.turbo_disabled || global.no_turbo ?
                                        cpu->pstate.max_freq :
                                        cpu->pstate.turbo_freq;
 
@@ -2203,9 +2157,9 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
                unsigned int max_freq, min_freq;
 
                max_freq = policy->cpuinfo.max_freq *
-                                       perf_limits->max_sysfs_pct / 100;
+                                       global.max_sysfs_pct / 100;
                min_freq = policy->cpuinfo.max_freq *
-                                       perf_limits->min_sysfs_pct / 100;
+                                       global.min_sysfs_pct / 100;
                cpufreq_verify_within_limits(policy, min_freq, max_freq);
        }
 
@@ -2257,7 +2211,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
        /* cpuinfo and default policy values */
        policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
        update_turbo_state();
-       policy->cpuinfo.max_freq = limits->turbo_disabled ?
+       policy->cpuinfo.max_freq = global.turbo_disabled ?
                        cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
        policy->cpuinfo.max_freq *= cpu->pstate.scaling;
 
@@ -2277,7 +2231,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
                return ret;
 
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100)
+       if (IS_ENABLED(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE))
                policy->policy = CPUFREQ_POLICY_PERFORMANCE;
        else
                policy->policy = CPUFREQ_POLICY_POWERSAVE;
@@ -2303,7 +2257,7 @@ static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
        struct cpudata *cpu = all_cpu_data[policy->cpu];
 
        update_turbo_state();
-       policy->cpuinfo.max_freq = limits->turbo_disabled ?
+       policy->cpuinfo.max_freq = global.no_turbo || global.turbo_disabled ?
                        cpu->pstate.max_freq : cpu->pstate.turbo_freq;
 
        cpufreq_verify_within_cpu_limits(policy);
@@ -2311,26 +2265,6 @@ static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
        return 0;
 }
 
-static unsigned int intel_cpufreq_turbo_update(struct cpudata *cpu,
-                                              struct cpufreq_policy *policy,
-                                              unsigned int target_freq)
-{
-       unsigned int max_freq;
-
-       update_turbo_state();
-
-       max_freq = limits->no_turbo || limits->turbo_disabled ?
-                       cpu->pstate.max_freq : cpu->pstate.turbo_freq;
-       policy->cpuinfo.max_freq = max_freq;
-       if (policy->max > max_freq)
-               policy->max = max_freq;
-
-       if (target_freq > max_freq)
-               target_freq = max_freq;
-
-       return target_freq;
-}
-
 static int intel_cpufreq_target(struct cpufreq_policy *policy,
                                unsigned int target_freq,
                                unsigned int relation)
@@ -2339,8 +2273,10 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy,
        struct cpufreq_freqs freqs;
        int target_pstate;
 
+       update_turbo_state();
+
        freqs.old = policy->cur;
-       freqs.new = intel_cpufreq_turbo_update(cpu, policy, target_freq);
+       freqs.new = target_freq;
 
        cpufreq_freq_transition_begin(policy, &freqs);
        switch (relation) {
@@ -2372,7 +2308,8 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
        struct cpudata *cpu = all_cpu_data[policy->cpu];
        int target_pstate;
 
-       target_freq = intel_cpufreq_turbo_update(cpu, policy, target_freq);
+       update_turbo_state();
+
        target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling);
        target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
        intel_pstate_update_pstate(cpu, target_pstate);
@@ -2427,13 +2364,7 @@ static int intel_pstate_register_driver(void)
 {
        int ret;
 
-       intel_pstate_init_limits(&powersave_limits);
-       intel_pstate_set_performance_limits(&performance_limits);
-       if (IS_ENABLED(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE) &&
-           intel_pstate_driver == &intel_pstate)
-               limits = &performance_limits;
-       else
-               limits = &powersave_limits;
+       intel_pstate_init_limits(&global);
 
        ret = cpufreq_register_driver(intel_pstate_driver);
        if (ret) {
index c5adc8c9ac43afeffb0f7ca842f730df76ef8eb1..ae948b1da93a379b12d16aaf98be5df6ac762da4 100644 (file)
@@ -615,6 +615,18 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
        struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
        int error;
 
+       /*
+        * Return if cpu_device is not setup for this CPU.
+        *
+        * This could happen if the arch did not set up cpu_device
+        * since this CPU is not in cpu_present mask and the
+        * driver did not send a correct CPU mask during registration.
+        * Without this check we would end up passing bogus
+        * value for &cpu_dev->kobj in kobject_init_and_add()
+        */
+       if (!cpu_dev)
+               return -ENODEV;
+
        kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
        if (!kdev)
                return -ENOMEM;
index 511ab042b5e7939b008045129de0c9e268f2db46..92d1c6959f08b8943f513a9ed5fd8525c2d6b702 100644 (file)
@@ -283,11 +283,14 @@ EXPORT_SYMBOL_GPL(ccp_version);
  */
 int ccp_enqueue_cmd(struct ccp_cmd *cmd)
 {
-       struct ccp_device *ccp = ccp_get_device();
+       struct ccp_device *ccp;
        unsigned long flags;
        unsigned int i;
        int ret;
 
+       /* Some commands might need to be sent to a specific device */
+       ccp = cmd->ccp ? cmd->ccp : ccp_get_device();
+
        if (!ccp)
                return -ENODEV;
 
index e5d9278f40197427e913993fe9249d405585fe87..8d0eeb46d4a27437678a34da89f090db2d625c45 100644 (file)
@@ -390,6 +390,7 @@ static struct ccp_dma_desc *ccp_create_desc(struct dma_chan *dma_chan,
                        goto err;
 
                ccp_cmd = &cmd->ccp_cmd;
+               ccp_cmd->ccp = chan->ccp;
                ccp_pt = &ccp_cmd->u.passthru_nomap;
                ccp_cmd->flags = CCP_CMD_MAY_BACKLOG;
                ccp_cmd->flags |= CCP_CMD_PASSTHRU_NO_DMA_MAP;
index dce1af0ce85ce8ec6dbd7184f02776cb173c41f0..1b9da3dc799b05dff2971e6a5415cc3ae3d4bd85 100644 (file)
@@ -270,7 +270,7 @@ static void s5p_sg_copy_buf(void *buf, struct scatterlist *sg,
        scatterwalk_done(&walk, out, 0);
 }
 
-static void s5p_aes_complete(struct s5p_aes_dev *dev, int err)
+static void s5p_sg_done(struct s5p_aes_dev *dev)
 {
        if (dev->sg_dst_cpy) {
                dev_dbg(dev->dev,
@@ -281,8 +281,11 @@ static void s5p_aes_complete(struct s5p_aes_dev *dev, int err)
        }
        s5p_free_sg_cpy(dev, &dev->sg_src_cpy);
        s5p_free_sg_cpy(dev, &dev->sg_dst_cpy);
+}
 
-       /* holding a lock outside */
+/* Calls the completion. Cannot be called with dev->lock hold. */
+static void s5p_aes_complete(struct s5p_aes_dev *dev, int err)
+{
        dev->req->base.complete(&dev->req->base, err);
        dev->busy = false;
 }
@@ -368,51 +371,44 @@ exit:
 }
 
 /*
- * Returns true if new transmitting (output) data is ready and its
- * address+length have to be written to device (by calling
- * s5p_set_dma_outdata()). False otherwise.
+ * Returns -ERRNO on error (mapping of new data failed).
+ * On success returns:
+ *  - 0 if there is no more data,
+ *  - 1 if new transmitting (output) data is ready and its address+length
+ *     have to be written to device (by calling s5p_set_dma_outdata()).
  */
-static bool s5p_aes_tx(struct s5p_aes_dev *dev)
+static int s5p_aes_tx(struct s5p_aes_dev *dev)
 {
-       int err = 0;
-       bool ret = false;
+       int ret = 0;
 
        s5p_unset_outdata(dev);
 
        if (!sg_is_last(dev->sg_dst)) {
-               err = s5p_set_outdata(dev, sg_next(dev->sg_dst));
-               if (err)
-                       s5p_aes_complete(dev, err);
-               else
-                       ret = true;
-       } else {
-               s5p_aes_complete(dev, err);
-
-               dev->busy = true;
-               tasklet_schedule(&dev->tasklet);
+               ret = s5p_set_outdata(dev, sg_next(dev->sg_dst));
+               if (!ret)
+                       ret = 1;
        }
 
        return ret;
 }
 
 /*
- * Returns true if new receiving (input) data is ready and its
- * address+length have to be written to device (by calling
- * s5p_set_dma_indata()). False otherwise.
+ * Returns -ERRNO on error (mapping of new data failed).
+ * On success returns:
+ *  - 0 if there is no more data,
+ *  - 1 if new receiving (input) data is ready and its address+length
+ *     have to be written to device (by calling s5p_set_dma_indata()).
  */
-static bool s5p_aes_rx(struct s5p_aes_dev *dev)
+static int s5p_aes_rx(struct s5p_aes_dev *dev/*, bool *set_dma*/)
 {
-       int err;
-       bool ret = false;
+       int ret = 0;
 
        s5p_unset_indata(dev);
 
        if (!sg_is_last(dev->sg_src)) {
-               err = s5p_set_indata(dev, sg_next(dev->sg_src));
-               if (err)
-                       s5p_aes_complete(dev, err);
-               else
-                       ret = true;
+               ret = s5p_set_indata(dev, sg_next(dev->sg_src));
+               if (!ret)
+                       ret = 1;
        }
 
        return ret;
@@ -422,33 +418,73 @@ static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id)
 {
        struct platform_device *pdev = dev_id;
        struct s5p_aes_dev *dev = platform_get_drvdata(pdev);
-       bool set_dma_tx = false;
-       bool set_dma_rx = false;
+       int err_dma_tx = 0;
+       int err_dma_rx = 0;
+       bool tx_end = false;
        unsigned long flags;
        uint32_t status;
+       int err;
 
        spin_lock_irqsave(&dev->lock, flags);
 
+       /*
+        * Handle rx or tx interrupt. If there is still data (scatterlist did not
+        * reach end), then map next scatterlist entry.
+        * In case of such mapping error, s5p_aes_complete() should be called.
+        *
+        * If there is no more data in tx scatter list, call s5p_aes_complete()
+        * and schedule new tasklet.
+        */
        status = SSS_READ(dev, FCINTSTAT);
        if (status & SSS_FCINTSTAT_BRDMAINT)
-               set_dma_rx = s5p_aes_rx(dev);
-       if (status & SSS_FCINTSTAT_BTDMAINT)
-               set_dma_tx = s5p_aes_tx(dev);
+               err_dma_rx = s5p_aes_rx(dev);
+
+       if (status & SSS_FCINTSTAT_BTDMAINT) {
+               if (sg_is_last(dev->sg_dst))
+                       tx_end = true;
+               err_dma_tx = s5p_aes_tx(dev);
+       }
 
        SSS_WRITE(dev, FCINTPEND, status);
 
-       /*
-        * Writing length of DMA block (either receiving or transmitting)
-        * will start the operation immediately, so this should be done
-        * at the end (even after clearing pending interrupts to not miss the
-        * interrupt).
-        */
-       if (set_dma_tx)
-               s5p_set_dma_outdata(dev, dev->sg_dst);
-       if (set_dma_rx)
-               s5p_set_dma_indata(dev, dev->sg_src);
+       if (err_dma_rx < 0) {
+               err = err_dma_rx;
+               goto error;
+       }
+       if (err_dma_tx < 0) {
+               err = err_dma_tx;
+               goto error;
+       }
+
+       if (tx_end) {
+               s5p_sg_done(dev);
+
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               s5p_aes_complete(dev, 0);
+               dev->busy = true;
+               tasklet_schedule(&dev->tasklet);
+       } else {
+               /*
+                * Writing length of DMA block (either receiving or
+                * transmitting) will start the operation immediately, so this
+                * should be done at the end (even after clearing pending
+                * interrupts to not miss the interrupt).
+                */
+               if (err_dma_tx == 1)
+                       s5p_set_dma_outdata(dev, dev->sg_dst);
+               if (err_dma_rx == 1)
+                       s5p_set_dma_indata(dev, dev->sg_src);
 
+               spin_unlock_irqrestore(&dev->lock, flags);
+       }
+
+       return IRQ_HANDLED;
+
+error:
+       s5p_sg_done(dev);
        spin_unlock_irqrestore(&dev->lock, flags);
+       s5p_aes_complete(dev, err);
 
        return IRQ_HANDLED;
 }
@@ -597,8 +633,9 @@ outdata_error:
        s5p_unset_indata(dev);
 
 indata_error:
-       s5p_aes_complete(dev, err);
+       s5p_sg_done(dev);
        spin_unlock_irqrestore(&dev->lock, flags);
+       s5p_aes_complete(dev, err);
 }
 
 static void s5p_tasklet_cb(unsigned long data)
@@ -805,8 +842,9 @@ static int s5p_aes_probe(struct platform_device *pdev)
                dev_warn(dev, "feed control interrupt is not available.\n");
                goto err_irq;
        }
-       err = devm_request_irq(dev, pdata->irq_fc, s5p_aes_interrupt,
-                              IRQF_SHARED, pdev->name, pdev);
+       err = devm_request_threaded_irq(dev, pdata->irq_fc, NULL,
+                                       s5p_aes_interrupt, IRQF_ONESHOT,
+                                       pdev->name, pdev);
        if (err < 0) {
                dev_warn(dev, "feed control interrupt is not available.\n");
                goto err_irq;
index 8d9829ff2a784de9490404a86a194e2304ed65c7..80c6db279ae10cb8558b2e90a91a4c4dafa917e0 100644 (file)
@@ -427,6 +427,7 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
        int rc = VM_FAULT_SIGBUS;
        phys_addr_t phys;
        pfn_t pfn;
+       unsigned int fault_size = PAGE_SIZE;
 
        if (check_vma(dax_dev, vmf->vma, __func__))
                return VM_FAULT_SIGBUS;
@@ -437,9 +438,12 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
        }
 
+       if (fault_size != dax_region->align)
+               return VM_FAULT_SIGBUS;
+
        phys = pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE);
        if (phys == -1) {
-               dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
+               dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
                                vmf->pgoff);
                return VM_FAULT_SIGBUS;
        }
@@ -464,6 +468,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
        phys_addr_t phys;
        pgoff_t pgoff;
        pfn_t pfn;
+       unsigned int fault_size = PMD_SIZE;
 
        if (check_vma(dax_dev, vmf->vma, __func__))
                return VM_FAULT_SIGBUS;
@@ -480,10 +485,20 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
        }
 
+       if (fault_size < dax_region->align)
+               return VM_FAULT_SIGBUS;
+       else if (fault_size > dax_region->align)
+               return VM_FAULT_FALLBACK;
+
+       /* if we are outside of the VMA */
+       if (pmd_addr < vmf->vma->vm_start ||
+                       (pmd_addr + PMD_SIZE) > vmf->vma->vm_end)
+               return VM_FAULT_SIGBUS;
+
        pgoff = linear_page_index(vmf->vma, pmd_addr);
        phys = pgoff_to_phys(dax_dev, pgoff, PMD_SIZE);
        if (phys == -1) {
-               dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
+               dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
                                pgoff);
                return VM_FAULT_SIGBUS;
        }
@@ -503,6 +518,8 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
        phys_addr_t phys;
        pgoff_t pgoff;
        pfn_t pfn;
+       unsigned int fault_size = PUD_SIZE;
+
 
        if (check_vma(dax_dev, vmf->vma, __func__))
                return VM_FAULT_SIGBUS;
@@ -519,10 +536,20 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
        }
 
+       if (fault_size < dax_region->align)
+               return VM_FAULT_SIGBUS;
+       else if (fault_size > dax_region->align)
+               return VM_FAULT_FALLBACK;
+
+       /* if we are outside of the VMA */
+       if (pud_addr < vmf->vma->vm_start ||
+                       (pud_addr + PUD_SIZE) > vmf->vma->vm_end)
+               return VM_FAULT_SIGBUS;
+
        pgoff = linear_page_index(vmf->vma, pud_addr);
        phys = pgoff_to_phys(dax_dev, pgoff, PUD_SIZE);
        if (phys == -1) {
-               dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
+               dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
                                pgoff);
                return VM_FAULT_SIGBUS;
        }
index 9e1a138fed53372a56dd1b7d2982ec198f46b3f1..16a8951b2beda389368c858848beb2edaf06949f 100644 (file)
@@ -96,7 +96,7 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev)
        gpio->regmap = a10sr->regmap;
 
        gpio->gp = altr_a10sr_gc;
-
+       gpio->gp.parent = pdev->dev.parent;
        gpio->gp.of_node = pdev->dev.of_node;
 
        ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
index 5bddbd507ca9f105aa18cfe5f43b673b676d551d..3fe6a21e05a5718d8769bf2dd505cb5968f41207 100644 (file)
@@ -90,21 +90,18 @@ static int altera_gpio_irq_set_type(struct irq_data *d,
 
        altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
 
-       if (type == IRQ_TYPE_NONE)
+       if (type == IRQ_TYPE_NONE) {
+               irq_set_handler_locked(d, handle_bad_irq);
                return 0;
-       if (type == IRQ_TYPE_LEVEL_HIGH &&
-               altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH)
-               return 0;
-       if (type == IRQ_TYPE_EDGE_RISING &&
-               altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_RISING)
-               return 0;
-       if (type == IRQ_TYPE_EDGE_FALLING &&
-               altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_FALLING)
-               return 0;
-       if (type == IRQ_TYPE_EDGE_BOTH &&
-               altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_BOTH)
+       }
+       if (type == altera_gc->interrupt_trigger) {
+               if (type == IRQ_TYPE_LEVEL_HIGH)
+                       irq_set_handler_locked(d, handle_level_irq);
+               else
+                       irq_set_handler_locked(d, handle_simple_irq);
                return 0;
-
+       }
+       irq_set_handler_locked(d, handle_bad_irq);
        return -EINVAL;
 }
 
@@ -230,7 +227,6 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-
 static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
 {
        struct altera_gpio_chip *altera_gc;
@@ -310,7 +306,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
        altera_gc->interrupt_trigger = reg;
 
        ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0,
-               handle_simple_irq, IRQ_TYPE_NONE);
+               handle_bad_irq, IRQ_TYPE_NONE);
 
        if (ret) {
                dev_err(&pdev->dev, "could not add irqchip\n");
index bdb692345428ccc99c8f22bd3b460f25b41e3156..2a57d024481db8c354badd976843f83a365c72a9 100644 (file)
@@ -270,8 +270,10 @@ mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 static irqreturn_t mcp23s08_irq(int irq, void *data)
 {
        struct mcp23s08 *mcp = data;
-       int intcap, intf, i;
+       int intcap, intf, i, gpio, gpio_orig, intcap_mask;
        unsigned int child_irq;
+       bool intf_set, intcap_changed, gpio_bit_changed,
+               defval_changed, gpio_set;
 
        mutex_lock(&mcp->lock);
        if (mcp_read(mcp, MCP_INTF, &intf) < 0) {
@@ -287,14 +289,67 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
        }
 
        mcp->cache[MCP_INTCAP] = intcap;
+
+       /* This clears the interrupt(configurable on S18) */
+       if (mcp_read(mcp, MCP_GPIO, &gpio) < 0) {
+               mutex_unlock(&mcp->lock);
+               return IRQ_HANDLED;
+       }
+       gpio_orig = mcp->cache[MCP_GPIO];
+       mcp->cache[MCP_GPIO] = gpio;
        mutex_unlock(&mcp->lock);
 
+       if (mcp->cache[MCP_INTF] == 0) {
+               /* There is no interrupt pending */
+               return IRQ_HANDLED;
+       }
+
+       dev_dbg(mcp->chip.parent,
+               "intcap 0x%04X intf 0x%04X gpio_orig 0x%04X gpio 0x%04X\n",
+               intcap, intf, gpio_orig, gpio);
 
        for (i = 0; i < mcp->chip.ngpio; i++) {
-               if ((BIT(i) & mcp->cache[MCP_INTF]) &&
-                   ((BIT(i) & intcap & mcp->irq_rise) ||
-                    (mcp->irq_fall & ~intcap & BIT(i)) ||
-                    (BIT(i) & mcp->cache[MCP_INTCON]))) {
+               /* We must check all of the inputs on the chip,
+                * otherwise we may not notice a change on >=2 pins.
+                *
+                * On at least the mcp23s17, INTCAP is only updated
+                * one byte at a time(INTCAPA and INTCAPB are
+                * not written to at the same time - only on a per-bank
+                * basis).
+                *
+                * INTF only contains the single bit that caused the
+                * interrupt per-bank.  On the mcp23s17, there is
+                * INTFA and INTFB.  If two pins are changed on the A
+                * side at the same time, INTF will only have one bit
+                * set.  If one pin on the A side and one pin on the B
+                * side are changed at the same time, INTF will have
+                * two bits set.  Thus, INTF can't be the only check
+                * to see if the input has changed.
+                */
+
+               intf_set = BIT(i) & mcp->cache[MCP_INTF];
+               if (i < 8 && intf_set)
+                       intcap_mask = 0x00FF;
+               else if (i >= 8 && intf_set)
+                       intcap_mask = 0xFF00;
+               else
+                       intcap_mask = 0x00;
+
+               intcap_changed = (intcap_mask &
+                       (BIT(i) & mcp->cache[MCP_INTCAP])) !=
+                       (intcap_mask & (BIT(i) & gpio_orig));
+               gpio_set = BIT(i) & mcp->cache[MCP_GPIO];
+               gpio_bit_changed = (BIT(i) & gpio_orig) !=
+                       (BIT(i) & mcp->cache[MCP_GPIO]);
+               defval_changed = (BIT(i) & mcp->cache[MCP_INTCON]) &&
+                       ((BIT(i) & mcp->cache[MCP_GPIO]) !=
+                       (BIT(i) & mcp->cache[MCP_DEFVAL]));
+
+               if (((gpio_bit_changed || intcap_changed) &&
+                       (BIT(i) & mcp->irq_rise) && gpio_set) ||
+                   ((gpio_bit_changed || intcap_changed) &&
+                       (BIT(i) & mcp->irq_fall) && !gpio_set) ||
+                   defval_changed) {
                        child_irq = irq_find_mapping(mcp->chip.irqdomain, i);
                        handle_nested_irq(child_irq);
                }
index 06dac72cb69c0c1c6e9005c748a613985dea111b..d993386892138757b67be09b4df8a822e39e4017 100644 (file)
@@ -197,7 +197,7 @@ static ssize_t gpio_mockup_event_write(struct file *file,
        struct seq_file *sfile;
        struct gpio_desc *desc;
        struct gpio_chip *gc;
-       int status, val;
+       int val;
        char buf;
 
        sfile = file->private_data;
@@ -206,9 +206,8 @@ static ssize_t gpio_mockup_event_write(struct file *file,
        chip = priv->chip;
        gc = &chip->gc;
 
-       status = copy_from_user(&buf, usr_buf, 1);
-       if (status)
-               return status;
+       if (copy_from_user(&buf, usr_buf, 1))
+               return -EFAULT;
 
        if (buf == '0')
                val = 0;
index 40a8881c2ce882bc1eef7eb59fff492afa6f378b..f1c6ec17b90a8352ecaf2e350aa8309a317925d8 100644 (file)
@@ -42,9 +42,7 @@ struct xgene_gpio {
        struct gpio_chip        chip;
        void __iomem            *base;
        spinlock_t              lock;
-#ifdef CONFIG_PM
        u32                     set_dr_val[XGENE_MAX_GPIO_BANKS];
-#endif
 };
 
 static int xgene_gpio_get(struct gpio_chip *gc, unsigned int offset)
@@ -138,8 +136,7 @@ static int xgene_gpio_dir_out(struct gpio_chip *gc,
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int xgene_gpio_suspend(struct device *dev)
+static __maybe_unused int xgene_gpio_suspend(struct device *dev)
 {
        struct xgene_gpio *gpio = dev_get_drvdata(dev);
        unsigned long bank_offset;
@@ -152,7 +149,7 @@ static int xgene_gpio_suspend(struct device *dev)
        return 0;
 }
 
-static int xgene_gpio_resume(struct device *dev)
+static __maybe_unused int xgene_gpio_resume(struct device *dev)
 {
        struct xgene_gpio *gpio = dev_get_drvdata(dev);
        unsigned long bank_offset;
@@ -166,10 +163,6 @@ static int xgene_gpio_resume(struct device *dev)
 }
 
 static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume);
-#define XGENE_GPIO_PM_OPS      (&xgene_gpio_pm)
-#else
-#define XGENE_GPIO_PM_OPS      NULL
-#endif
 
 static int xgene_gpio_probe(struct platform_device *pdev)
 {
@@ -241,7 +234,7 @@ static struct platform_driver xgene_gpio_driver = {
                .name = "xgene-gpio",
                .of_match_table = xgene_gpio_of_match,
                .acpi_match_table = ACPI_PTR(xgene_gpio_acpi_match),
-               .pm     = XGENE_GPIO_PM_OPS,
+               .pm     = &xgene_gpio_pm,
        },
        .probe = xgene_gpio_probe,
 };
index 8363cb57915b0b726c704b8be37805ecef2a18ee..8a08e81ee90d579774ca96bc70853093ba623f09 100644 (file)
@@ -3,6 +3,4 @@
 # of AMDSOC/AMDGPU drm driver.
 # It provides the HW control for ACP related functionalities.
 
-subdir-ccflags-y += -I$(AMDACPPATH)/ -I$(AMDACPPATH)/include
-
 AMD_ACP_FILES := $(AMDACPPATH)/acp_hw.o
index d2d0f60ff36d1f2fd4a80ef8b43d2d3d9737e1f9..99424cb8020bdf914b5627bffce01155ba8f6b73 100644 (file)
@@ -240,6 +240,8 @@ free_partial_kdata:
        for (; i >= 0; i--)
                drm_free_large(p->chunks[i].kdata);
        kfree(p->chunks);
+       p->chunks = NULL;
+       p->nchunks = 0;
 put_ctx:
        amdgpu_ctx_put(p->ctx);
 free_chunk:
index 4120b351a8e5cc856492ad628f4d0567614dfe57..de0cf3315484c997877b30a65a15e7e1af3b87a4 100644 (file)
@@ -475,7 +475,7 @@ static int amdgpu_wb_init(struct amdgpu_device *adev)
        int r;
 
        if (adev->wb.wb_obj == NULL) {
-               r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * 4,
+               r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t),
                                            PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
                                            &adev->wb.wb_obj, &adev->wb.gpu_addr,
                                            (void **)&adev->wb.wb);
@@ -488,7 +488,7 @@ static int amdgpu_wb_init(struct amdgpu_device *adev)
                memset(&adev->wb.used, 0, sizeof(adev->wb.used));
 
                /* clear wb memory */
-               memset((char *)adev->wb.wb, 0, AMDGPU_GPU_PAGE_SIZE);
+               memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t));
        }
 
        return 0;
@@ -2590,7 +2590,7 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
                use_bank = 0;
        }
 
-       *pos &= 0x3FFFF;
+       *pos &= (1UL << 22) - 1;
 
        if (use_bank) {
                if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
@@ -2666,7 +2666,7 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
                use_bank = 0;
        }
 
-       *pos &= 0x3FFFF;
+       *pos &= (1UL << 22) - 1;
 
        if (use_bank) {
                if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
index f7adbace428a49ea77a47bf3d3590ec136b0d1fe..b76cd699eb0d7357d79d68f9da4fd9bd02f3e132 100644 (file)
@@ -421,6 +421,7 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        {0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        {0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        {0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
 
        {0, 0, 0}
index f55e45b52fbce2b658135bc5fc48b084332f811c..c5dec210d5299995c72ea79f95c05415306f034f 100644 (file)
@@ -3464,6 +3464,16 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
                    (adev->pdev->device == 0x6667)) {
                        max_sclk = 75000;
                }
+       } else if (adev->asic_type == CHIP_OLAND) {
+               if ((adev->pdev->revision == 0xC7) ||
+                   (adev->pdev->revision == 0x80) ||
+                   (adev->pdev->revision == 0x81) ||
+                   (adev->pdev->revision == 0x83) ||
+                   (adev->pdev->revision == 0x87) ||
+                   (adev->pdev->device == 0x6604) ||
+                   (adev->pdev->device == 0x6605)) {
+                       max_sclk = 75000;
+               }
        }
 
        if (rps->vce_active) {
index 50bdb24ef8d6e9f7e828ea661d873659beb3ce42..4a785d6acfb9afbde3b4f4b86116512134075759 100644 (file)
@@ -1051,7 +1051,7 @@ static int vi_common_early_init(void *handle)
                /* rev0 hardware requires workarounds to support PG */
                adev->pg_flags = 0;
                if (adev->rev_id != 0x00) {
-                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
+                       adev->pg_flags |=
                                AMD_PG_SUPPORT_GFX_SMG |
                                AMD_PG_SUPPORT_GFX_PIPELINE |
                                AMD_PG_SUPPORT_CP |
index 8cf71f3c6d0ea4706096222574c9d85871baba6c..261b828ad59086990f9f054906448a5526f4cbc4 100644 (file)
@@ -178,7 +178,7 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
        if (bgate) {
                cgs_set_powergating_state(hwmgr->device,
                                                AMD_IP_BLOCK_TYPE_VCE,
-                                               AMD_PG_STATE_UNGATE);
+                                               AMD_PG_STATE_GATE);
                cgs_set_clockgating_state(hwmgr->device,
                                AMD_IP_BLOCK_TYPE_VCE,
                                AMD_CG_STATE_GATE);
index 08e6a71f5d05f412946496f39ee82303d19a56a4..294b53697334cc0855daa73925b8c58a19cf2222 100644 (file)
@@ -63,8 +63,7 @@ static void malidp_crtc_enable(struct drm_crtc *crtc)
 
        clk_prepare_enable(hwdev->pxlclk);
 
-       /* mclk needs to be set to the same or higher rate than pxlclk */
-       clk_set_rate(hwdev->mclk, crtc->state->adjusted_mode.crtc_clock * 1000);
+       /* We rely on firmware to set mclk to a sensible level. */
        clk_set_rate(hwdev->pxlclk, crtc->state->adjusted_mode.crtc_clock * 1000);
 
        hwdev->modeset(hwdev, &vm);
index 488aedf5b58d54e7997b2339c75b7a90f30dcfc1..9f5513006eeef8b4e54f6727b44b0e97562935d6 100644 (file)
@@ -83,7 +83,7 @@ static const struct malidp_layer malidp550_layers[] = {
        { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
        { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE },
        { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
-       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 0 },
+       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE },
 };
 
 #define MALIDP_DE_DEFAULT_PREFETCH_START       5
index 414aada10fe5e7d43392aa835b4c01aba594bcb7..d5aec082294cbdde5a19986a5b1908aef974bb19 100644 (file)
@@ -37,6 +37,8 @@
 #define   LAYER_V_VAL(x)               (((x) & 0x1fff) << 16)
 #define MALIDP_LAYER_COMP_SIZE         0x010
 #define MALIDP_LAYER_OFFSET            0x014
+#define MALIDP550_LS_ENABLE            0x01c
+#define MALIDP550_LS_R1_IN_SIZE                0x020
 
 /*
  * This 4-entry look-up-table is used to determine the full 8-bit alpha value
@@ -242,6 +244,11 @@ static void malidp_de_plane_update(struct drm_plane *plane,
                        LAYER_V_VAL(plane->state->crtc_y),
                        mp->layer->base + MALIDP_LAYER_OFFSET);
 
+       if (mp->layer->id == DE_SMART)
+               malidp_hw_write(mp->hwdev,
+                               LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
+                               mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
+
        /* first clear the rotation bits */
        val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
        val &= ~LAYER_ROT_MASK;
@@ -330,9 +337,16 @@ int malidp_de_planes_init(struct drm_device *drm)
                plane->hwdev = malidp->dev;
                plane->layer = &map->layers[i];
 
-               /* Skip the features which the SMART layer doesn't have */
-               if (id == DE_SMART)
+               if (id == DE_SMART) {
+                       /*
+                        * Enable the first rectangle in the SMART layer to be
+                        * able to use it as a drm plane.
+                        */
+                       malidp_hw_write(malidp->dev, 1,
+                                       plane->layer->base + MALIDP550_LS_ENABLE);
+                       /* Skip the features which the SMART layer doesn't have. */
                        continue;
+               }
 
                drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
                malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
index aff6d4a84e998c6cc1d01e3067d0f52712daa145..b816067a65c5727ab120000c5d5d080e022fee2c 100644 (file)
@@ -84,6 +84,7 @@
 /* Stride register offsets relative to Lx_BASE */
 #define MALIDP_DE_LG_STRIDE            0x18
 #define MALIDP_DE_LV_STRIDE0           0x18
+#define MALIDP550_DE_LS_R1_STRIDE      0x28
 
 /* macros to set values into registers */
 #define MALIDP_DE_H_FRONTPORCH(x)      (((x) & 0xfff) << 0)
index f6d4d9700734e6d48792e90d47c7bfe4081116a1..324a688b3f3013e9020ce2b9f0f76083ad91f890 100644 (file)
@@ -1260,9 +1260,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
         * to KMS, hence fail if different settings are requested.
         */
        if (var->bits_per_pixel != fb->format->cpp[0] * 8 ||
-           var->xres != fb->width || var->yres != fb->height ||
-           var->xres_virtual != fb->width || var->yres_virtual != fb->height) {
-               DRM_DEBUG("fb userspace requested width/height/bpp different than current fb "
+           var->xres > fb->width || var->yres > fb->height ||
+           var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
+               DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
                          "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
                          var->xres, var->yres, var->bits_per_pixel,
                          var->xres_virtual, var->yres_virtual,
index 0fd6f7a18364a69ba67cb000674593fc94041e19..c0e8d3302292c9c9329ca4795b4d9ffb3465a178 100644 (file)
@@ -68,6 +68,8 @@ struct decon_context {
        unsigned long                   flags;
        unsigned long                   out_type;
        int                             first_win;
+       spinlock_t                      vblank_lock;
+       u32                             frame_id;
 };
 
 static const uint32_t decon_formats[] = {
@@ -103,7 +105,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
                if (ctx->out_type & IFTYPE_I80)
                        val |= VIDINTCON0_FRAMEDONE;
                else
-                       val |= VIDINTCON0_INTFRMEN;
+                       val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP;
 
                writel(val, ctx->addr + DECON_VIDINTCON0);
        }
@@ -122,14 +124,56 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
                writel(0, ctx->addr + DECON_VIDINTCON0);
 }
 
+/* return number of starts/ends of frame transmissions since reset */
+static u32 decon_get_frame_count(struct decon_context *ctx, bool end)
+{
+       u32 frm, pfrm, status, cnt = 2;
+
+       /* To get consistent result repeat read until frame id is stable.
+        * Usually the loop will be executed once, in rare cases when the loop
+        * is executed at frame change time 2nd pass will be needed.
+        */
+       frm = readl(ctx->addr + DECON_CRFMID);
+       do {
+               status = readl(ctx->addr + DECON_VIDCON1);
+               pfrm = frm;
+               frm = readl(ctx->addr + DECON_CRFMID);
+       } while (frm != pfrm && --cnt);
+
+       /* CRFMID is incremented on BPORCH in case of I80 and on VSYNC in case
+        * of RGB, it should be taken into account.
+        */
+       if (!frm)
+               return 0;
+
+       switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) {
+       case VIDCON1_VSTATUS_VS:
+               if (!(ctx->out_type & IFTYPE_I80))
+                       --frm;
+               break;
+       case VIDCON1_VSTATUS_BP:
+               --frm;
+               break;
+       case VIDCON1_I80_ACTIVE:
+       case VIDCON1_VSTATUS_AC:
+               if (end)
+                       --frm;
+               break;
+       default:
+               break;
+       }
+
+       return frm;
+}
+
 static void decon_setup_trigger(struct decon_context *ctx)
 {
        if (!(ctx->out_type & (IFTYPE_I80 | I80_HW_TRG)))
                return;
 
        if (!(ctx->out_type & I80_HW_TRG)) {
-               writel(TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN
-                      TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN,
+               writel(TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
+                      TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN,
                       ctx->addr + DECON_TRIGCON);
                return;
        }
@@ -365,11 +409,14 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
 static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
 {
        struct decon_context *ctx = crtc->ctx;
+       unsigned long flags;
        int i;
 
        if (test_bit(BIT_SUSPENDED, &ctx->flags))
                return;
 
+       spin_lock_irqsave(&ctx->vblank_lock, flags);
+
        for (i = ctx->first_win; i < WINDOWS_NR; i++)
                decon_shadow_protect_win(ctx, i, false);
 
@@ -378,11 +425,18 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
 
        if (ctx->out_type & IFTYPE_I80)
                set_bit(BIT_WIN_UPDATED, &ctx->flags);
+
+       ctx->frame_id = decon_get_frame_count(ctx, true);
+
+       exynos_crtc_handle_event(crtc);
+
+       spin_unlock_irqrestore(&ctx->vblank_lock, flags);
 }
 
 static void decon_swreset(struct decon_context *ctx)
 {
        unsigned int tries;
+       unsigned long flags;
 
        writel(0, ctx->addr + DECON_VIDCON0);
        for (tries = 2000; tries; --tries) {
@@ -400,6 +454,10 @@ static void decon_swreset(struct decon_context *ctx)
 
        WARN(tries == 0, "failed to software reset DECON\n");
 
+       spin_lock_irqsave(&ctx->vblank_lock, flags);
+       ctx->frame_id = 0;
+       spin_unlock_irqrestore(&ctx->vblank_lock, flags);
+
        if (!(ctx->out_type & IFTYPE_HDMI))
                return;
 
@@ -578,6 +636,24 @@ static const struct component_ops decon_component_ops = {
        .unbind = decon_unbind,
 };
 
+static void decon_handle_vblank(struct decon_context *ctx)
+{
+       u32 frm;
+
+       spin_lock(&ctx->vblank_lock);
+
+       frm = decon_get_frame_count(ctx, true);
+
+       if (frm != ctx->frame_id) {
+               /* handle only if incremented, take care of wrap-around */
+               if ((s32)(frm - ctx->frame_id) > 0)
+                       drm_crtc_handle_vblank(&ctx->crtc->base);
+               ctx->frame_id = frm;
+       }
+
+       spin_unlock(&ctx->vblank_lock);
+}
+
 static irqreturn_t decon_irq_handler(int irq, void *dev_id)
 {
        struct decon_context *ctx = dev_id;
@@ -598,7 +674,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
                            (VIDOUT_INTERLACE_EN_F | VIDOUT_INTERLACE_FIELD_F))
                                return IRQ_HANDLED;
                }
-               drm_crtc_handle_vblank(&ctx->crtc->base);
+               decon_handle_vblank(ctx);
        }
 
 out:
@@ -671,6 +747,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
        __set_bit(BIT_SUSPENDED, &ctx->flags);
        ctx->dev = dev;
        ctx->out_type = (unsigned long)of_device_get_match_data(dev);
+       spin_lock_init(&ctx->vblank_lock);
 
        if (ctx->out_type & IFTYPE_HDMI) {
                ctx->first_win = 1;
@@ -678,7 +755,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
                ctx->out_type |= IFTYPE_I80;
        }
 
-       if (ctx->out_type | I80_HW_TRG) {
+       if (ctx->out_type & I80_HW_TRG) {
                ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
                                                        "samsung,disp-sysreg");
                if (IS_ERR(ctx->sysreg)) {
index f9ab19e205e243d931412257064455582747e92a..48811806fa2727c540e5f5e9d0ffb1700dc08c4f 100644 (file)
@@ -526,6 +526,7 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
 
        for (i = 0; i < WINDOWS_NR; i++)
                decon_shadow_protect_win(ctx, i, false);
+       exynos_crtc_handle_event(crtc);
 }
 
 static void decon_init(struct decon_context *ctx)
index 5367b6664fe37d6ea1825eac48e620a7c6d902e7..c65f4509932c56f18f869f81b293d707ce2e47d7 100644 (file)
@@ -85,16 +85,28 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
                                     struct drm_crtc_state *old_crtc_state)
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-       struct drm_pending_vblank_event *event;
-       unsigned long flags;
 
        if (exynos_crtc->ops->atomic_flush)
                exynos_crtc->ops->atomic_flush(exynos_crtc);
+}
+
+static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
+       .enable         = exynos_drm_crtc_enable,
+       .disable        = exynos_drm_crtc_disable,
+       .mode_set_nofb  = exynos_drm_crtc_mode_set_nofb,
+       .atomic_check   = exynos_crtc_atomic_check,
+       .atomic_begin   = exynos_crtc_atomic_begin,
+       .atomic_flush   = exynos_crtc_atomic_flush,
+};
+
+void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc)
+{
+       struct drm_crtc *crtc = &exynos_crtc->base;
+       struct drm_pending_vblank_event *event = crtc->state->event;
+       unsigned long flags;
 
-       event = crtc->state->event;
        if (event) {
                crtc->state->event = NULL;
-
                spin_lock_irqsave(&crtc->dev->event_lock, flags);
                if (drm_crtc_vblank_get(crtc) == 0)
                        drm_crtc_arm_vblank_event(crtc, event);
@@ -105,15 +117,6 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
 
 }
 
-static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
-       .enable         = exynos_drm_crtc_enable,
-       .disable        = exynos_drm_crtc_disable,
-       .mode_set_nofb  = exynos_drm_crtc_mode_set_nofb,
-       .atomic_check   = exynos_crtc_atomic_check,
-       .atomic_begin   = exynos_crtc_atomic_begin,
-       .atomic_flush   = exynos_crtc_atomic_flush,
-};
-
 static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
index 6a581a8af4650fcf5f07ea3fa84c6b1dd5e81ad4..abd5d6ceac0c2fa0500650a139876d20ca9d3ea8 100644 (file)
@@ -40,4 +40,6 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
  */
 void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
 
+void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc);
+
 #endif
index 812e2ec0761d0b2b6ad17c71c99a37995e09ca51..d7ef26370e67c59fa2825a8be9303ab4f5b0c708 100644 (file)
@@ -86,7 +86,7 @@
 #define DSIM_SYNC_INFORM               (1 << 27)
 #define DSIM_EOT_DISABLE               (1 << 28)
 #define DSIM_MFLUSH_VS                 (1 << 29)
-/* This flag is valid only for exynos3250/3472/4415/5260/5430 */
+/* This flag is valid only for exynos3250/3472/5260/5430 */
 #define DSIM_CLKLANE_STOP              (1 << 30)
 
 /* DSIM_ESCMODE */
@@ -473,17 +473,6 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
        .reg_values = reg_values,
 };
 
-static const struct exynos_dsi_driver_data exynos4415_dsi_driver_data = {
-       .reg_ofs = exynos_reg_ofs,
-       .plltmr_reg = 0x58,
-       .has_clklane_stop = 1,
-       .num_clks = 2,
-       .max_freq = 1000,
-       .wait_for_reset = 1,
-       .num_bits_resol = 11,
-       .reg_values = reg_values,
-};
-
 static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
        .reg_ofs = exynos_reg_ofs,
        .plltmr_reg = 0x58,
@@ -521,8 +510,6 @@ static const struct of_device_id exynos_dsi_of_match[] = {
          .data = &exynos3_dsi_driver_data },
        { .compatible = "samsung,exynos4210-mipi-dsi",
          .data = &exynos4_dsi_driver_data },
-       { .compatible = "samsung,exynos4415-mipi-dsi",
-         .data = &exynos4415_dsi_driver_data },
        { .compatible = "samsung,exynos5410-mipi-dsi",
          .data = &exynos5_dsi_driver_data },
        { .compatible = "samsung,exynos5422-mipi-dsi",
@@ -979,7 +966,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,
        bool first = !xfer->tx_done;
        u32 reg;
 
-       dev_dbg(dev, "< xfer %p: tx len %u, done %u, rx len %u, done %u\n",
+       dev_dbg(dev, "< xfer %pK: tx len %u, done %u, rx len %u, done %u\n",
                xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done);
 
        if (length > DSI_TX_FIFO_SIZE)
@@ -1177,7 +1164,7 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)
        spin_unlock_irqrestore(&dsi->transfer_lock, flags);
 
        dev_dbg(dsi->dev,
-               "> xfer %p, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n",
+               "> xfer %pK, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n",
                xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len,
                xfer->rx_done);
 
@@ -1348,9 +1335,12 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi)
        int te_gpio_irq;
 
        dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0);
+       if (dsi->te_gpio == -ENOENT)
+               return 0;
+
        if (!gpio_is_valid(dsi->te_gpio)) {
-               dev_err(dsi->dev, "no te-gpios specified\n");
                ret = dsi->te_gpio;
+               dev_err(dsi->dev, "cannot get te-gpios, %d\n", ret);
                goto out;
        }
 
index 95871577015d8a5389cdae3a0c87413af7f0448f..5b18b5c5fdf255f262d68fc6fc7103f8d4d06910 100644 (file)
@@ -1695,7 +1695,7 @@ static int fimc_probe(struct platform_device *pdev)
                goto err_put_clk;
        }
 
-       DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
+       DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv);
 
        spin_lock_init(&ctx->lock);
        platform_set_drvdata(pdev, ctx);
index a9fa444c6053c0c8d048598198938d7fa2647cce..3f04d72c448d386fc9f646e1033c8528406b107e 100644 (file)
 #define TRIGCON                                0x1A4
 #define TRGMODE_ENABLE                 (1 << 0)
 #define SWTRGCMD_ENABLE                        (1 << 1)
-/* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */
+/* Exynos3250, 3472, 5260 5410, 5420 and 5422 only supported. */
 #define HWTRGEN_ENABLE                 (1 << 3)
 #define HWTRGMASK_ENABLE               (1 << 4)
-/* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */
+/* Exynos3250, 3472, 5260, 5420 and 5422 only supported. */
 #define HWTRIGEN_PER_ENABLE            (1 << 31)
 
 /* display mode change control register except exynos4 */
@@ -138,18 +138,6 @@ static struct fimd_driver_data exynos4_fimd_driver_data = {
        .has_vtsel = 1,
 };
 
-static struct fimd_driver_data exynos4415_fimd_driver_data = {
-       .timing_base = 0x20000,
-       .lcdblk_offset = 0x210,
-       .lcdblk_vt_shift = 10,
-       .lcdblk_bypass_shift = 1,
-       .trg_type = I80_HW_TRG,
-       .has_shadowcon = 1,
-       .has_vidoutcon = 1,
-       .has_vtsel = 1,
-       .has_trigger_per_te = 1,
-};
-
 static struct fimd_driver_data exynos5_fimd_driver_data = {
        .timing_base = 0x20000,
        .lcdblk_offset = 0x214,
@@ -210,8 +198,6 @@ static const struct of_device_id fimd_driver_dt_match[] = {
          .data = &exynos3_fimd_driver_data },
        { .compatible = "samsung,exynos4210-fimd",
          .data = &exynos4_fimd_driver_data },
-       { .compatible = "samsung,exynos4415-fimd",
-         .data = &exynos4415_fimd_driver_data },
        { .compatible = "samsung,exynos5250-fimd",
          .data = &exynos5_fimd_driver_data },
        { .compatible = "samsung,exynos5420-fimd",
@@ -257,7 +243,7 @@ static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
                        val |= VIDINTCON0_INT_FRAME;
 
                        val &= ~VIDINTCON0_FRAMESEL0_MASK;
-                       val |= VIDINTCON0_FRAMESEL0_VSYNC;
+                       val |= VIDINTCON0_FRAMESEL0_FRONTPORCH;
                        val &= ~VIDINTCON0_FRAMESEL1_MASK;
                        val |= VIDINTCON0_FRAMESEL1_NONE;
                }
@@ -723,6 +709,8 @@ static void fimd_atomic_flush(struct exynos_drm_crtc *crtc)
 
        for (i = 0; i < WINDOWS_NR; i++)
                fimd_shadow_protect_win(ctx, i, false);
+
+       exynos_crtc_handle_event(crtc);
 }
 
 static void fimd_update_plane(struct exynos_drm_crtc *crtc,
index 4c28f7ffcc4dd1a0593e5c37bb878f6481f1ed70..55a1579d11b3d7c1ce604eeba2988de78de61e0b 100644 (file)
@@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
                return ERR_PTR(ret);
        }
 
-       DRM_DEBUG_KMS("created file object = %p\n", obj->filp);
+       DRM_DEBUG_KMS("created file object = %pK\n", obj->filp);
 
        return exynos_gem;
 }
index bef57987759d2c8d2da9451a80c02b7b1c370b7f..0506b2b17ac1c45a1bea639cb37ed90075be3677 100644 (file)
@@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
+       DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv);
 
        mutex_init(&ctx->lock);
        platform_set_drvdata(pdev, ctx);
index 9c84ee76f18adc0ab1b8dcc3f406a4021346ece8..3edda18cc2d2d61b7010b57817aeecababe1d4c5 100644 (file)
@@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
         * e.g PAUSE state, queue buf, command control.
         */
        list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
-               DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", count++, ippdrv);
+               DRM_DEBUG_KMS("count[%d]ippdrv[%pK]\n", count++, ippdrv);
 
                mutex_lock(&ippdrv->cmd_lock);
                list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
@@ -388,7 +388,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
        }
        property->prop_id = ret;
 
-       DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%p]\n",
+       DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%pK]\n",
                property->prop_id, property->cmd, ippdrv);
 
        /* stored property information and ippdrv in private data */
@@ -518,7 +518,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
 {
        int i;
 
-       DRM_DEBUG_KMS("node[%p]\n", m_node);
+       DRM_DEBUG_KMS("node[%pK]\n", m_node);
 
        if (!m_node) {
                DRM_ERROR("invalid dequeue node.\n");
@@ -562,7 +562,7 @@ static struct drm_exynos_ipp_mem_node
        m_node->buf_id = qbuf->buf_id;
        INIT_LIST_HEAD(&m_node->list);
 
-       DRM_DEBUG_KMS("m_node[%p]ops_id[%d]\n", m_node, qbuf->ops_id);
+       DRM_DEBUG_KMS("m_node[%pK]ops_id[%d]\n", m_node, qbuf->ops_id);
        DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);
 
        for_each_ipp_planar(i) {
@@ -659,7 +659,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
 
        mutex_lock(&c_node->event_lock);
        list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
-               DRM_DEBUG_KMS("count[%d]e[%p]\n", count++, e);
+               DRM_DEBUG_KMS("count[%d]e[%pK]\n", count++, e);
 
                /*
                 * qbuf == NULL condition means all event deletion.
@@ -750,7 +750,7 @@ static struct drm_exynos_ipp_mem_node
 
        /* find memory node from memory list */
        list_for_each_entry(m_node, head, list) {
-               DRM_DEBUG_KMS("count[%d]m_node[%p]\n", count++, m_node);
+               DRM_DEBUG_KMS("count[%d]m_node[%pK]\n", count++, m_node);
 
                /* compare buffer id */
                if (m_node->buf_id == qbuf->buf_id)
@@ -767,7 +767,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
        struct exynos_drm_ipp_ops *ops = NULL;
        int ret = 0;
 
-       DRM_DEBUG_KMS("node[%p]\n", m_node);
+       DRM_DEBUG_KMS("node[%pK]\n", m_node);
 
        if (!m_node) {
                DRM_ERROR("invalid queue node.\n");
@@ -1232,7 +1232,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
                        m_node = list_first_entry(head,
                                struct drm_exynos_ipp_mem_node, list);
 
-                       DRM_DEBUG_KMS("m_node[%p]\n", m_node);
+                       DRM_DEBUG_KMS("m_node[%pK]\n", m_node);
 
                        ret = ipp_set_mem_node(ippdrv, c_node, m_node);
                        if (ret) {
@@ -1601,7 +1601,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
                }
                ippdrv->prop_list.ipp_id = ret;
 
-               DRM_DEBUG_KMS("count[%d]ippdrv[%p]ipp_id[%d]\n",
+               DRM_DEBUG_KMS("count[%d]ippdrv[%pK]ipp_id[%d]\n",
                        count++, ippdrv, ret);
 
                /* store parent device for node */
@@ -1659,7 +1659,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
 
        file_priv->ipp_dev = dev;
 
-       DRM_DEBUG_KMS("done priv[%p]\n", dev);
+       DRM_DEBUG_KMS("done priv[%pK]\n", dev);
 
        return 0;
 }
@@ -1676,7 +1676,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
                mutex_lock(&ippdrv->cmd_lock);
                list_for_each_entry_safe(c_node, tc_node,
                        &ippdrv->cmd_list, list) {
-                       DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n",
+                       DRM_DEBUG_KMS("count[%d]ippdrv[%pK]\n",
                                count++, ippdrv);
 
                        if (c_node->filp == file) {
index 6591e406084c164d30c1945aa2f6d7ce559c67fd..79282a820ecce104a59c828beac7be68b65a21ee 100644 (file)
@@ -748,7 +748,7 @@ static int rotator_probe(struct platform_device *pdev)
                goto err_ippdrv_register;
        }
 
-       DRM_DEBUG_KMS("ippdrv[%p]\n", ippdrv);
+       DRM_DEBUG_KMS("ippdrv[%pK]\n", ippdrv);
 
        platform_set_drvdata(pdev, rot);
 
index 57fe514d5c5bf9adc9f423d9f46a51e25aedfa46..5d9a62a87eec75f574ea0e696f31059d5802fa7d 100644 (file)
@@ -170,6 +170,7 @@ static const struct exynos_drm_crtc_ops vidi_crtc_ops = {
        .enable_vblank = vidi_enable_vblank,
        .disable_vblank = vidi_disable_vblank,
        .update_plane = vidi_update_plane,
+       .atomic_flush = exynos_crtc_handle_event,
 };
 
 static void vidi_fake_vblank_timer(unsigned long arg)
index 72143ac1052526ffc03332c5b6b211ae7bf30216..25edb635a197621871d583e26b3d31d3717a82fa 100644 (file)
@@ -1012,6 +1012,7 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
                return;
 
        mixer_vsync_set_update(mixer_ctx, true);
+       exynos_crtc_handle_event(crtc);
 }
 
 static void mixer_enable(struct exynos_drm_crtc *crtc)
index 3b6caaca975135d6b8d595393ffc372bc14107bc..325618d969feedf035196c9e3d211affe2fd82f6 100644 (file)
@@ -242,7 +242,7 @@ static int alloc_resource(struct intel_vgpu *vgpu,
        const char *item;
 
        if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) {
-               gvt_err("Invalid vGPU creation params\n");
+               gvt_vgpu_err("Invalid vGPU creation params\n");
                return -EINVAL;
        }
 
@@ -285,9 +285,9 @@ static int alloc_resource(struct intel_vgpu *vgpu,
        return 0;
 
 no_enough_resource:
-       gvt_err("vgpu%d: fail to allocate resource %s\n", vgpu->id, item);
-       gvt_err("vgpu%d: request %luMB avail %luMB max %luMB taken %luMB\n",
-               vgpu->id, BYTES_TO_MB(request), BYTES_TO_MB(avail),
+       gvt_vgpu_err("fail to allocate resource %s\n", item);
+       gvt_vgpu_err("request %luMB avail %luMB max %luMB taken %luMB\n",
+               BYTES_TO_MB(request), BYTES_TO_MB(avail),
                BYTES_TO_MB(max), BYTES_TO_MB(taken));
        return -ENOSPC;
 }
index 7ae6e2b241c829efdfddfa7f826c182e0078aae5..2b92cc8a7d1aa551778917ed038bc6aa7961ce3e 100644 (file)
@@ -817,6 +817,25 @@ static bool is_shadowed_mmio(unsigned int offset)
        return ret;
 }
 
+static inline bool is_force_nonpriv_mmio(unsigned int offset)
+{
+       return (offset >= 0x24d0 && offset < 0x2500);
+}
+
+static int force_nonpriv_reg_handler(struct parser_exec_state *s,
+                                    unsigned int offset, unsigned int index)
+{
+       struct intel_gvt *gvt = s->vgpu->gvt;
+       unsigned int data = cmd_val(s, index + 1);
+
+       if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data)) {
+               gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n",
+                       offset, data);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static int cmd_reg_handler(struct parser_exec_state *s,
        unsigned int offset, unsigned int index, char *cmd)
 {
@@ -824,23 +843,26 @@ static int cmd_reg_handler(struct parser_exec_state *s,
        struct intel_gvt *gvt = vgpu->gvt;
 
        if (offset + 4 > gvt->device_info.mmio_size) {
-               gvt_err("%s access to (%x) outside of MMIO range\n",
+               gvt_vgpu_err("%s access to (%x) outside of MMIO range\n",
                                cmd, offset);
                return -EINVAL;
        }
 
        if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) {
-               gvt_err("vgpu%d: %s access to non-render register (%x)\n",
-                               s->vgpu->id, cmd, offset);
+               gvt_vgpu_err("%s access to non-render register (%x)\n",
+                               cmd, offset);
                return 0;
        }
 
        if (is_shadowed_mmio(offset)) {
-               gvt_err("vgpu%d: found access of shadowed MMIO %x\n",
-                               s->vgpu->id, offset);
+               gvt_vgpu_err("found access of shadowed MMIO %x\n", offset);
                return 0;
        }
 
+       if (is_force_nonpriv_mmio(offset) &&
+           force_nonpriv_reg_handler(s, offset, index))
+               return -EINVAL;
+
        if (offset == i915_mmio_reg_offset(DERRMR) ||
                offset == i915_mmio_reg_offset(FORCEWAKE_MT)) {
                /* Writing to HW VGT_PVINFO_PAGE offset will be discarded */
@@ -1008,7 +1030,7 @@ static int cmd_handler_pipe_control(struct parser_exec_state *s)
                        ret = cmd_reg_handler(s, 0x2358, 1, "pipe_ctrl");
                else if (post_sync == 1) {
                        /* check ggtt*/
-                       if ((cmd_val(s, 2) & (1 << 2))) {
+                       if ((cmd_val(s, 1) & PIPE_CONTROL_GLOBAL_GTT_IVB)) {
                                gma = cmd_val(s, 2) & GENMASK(31, 3);
                                if (gmadr_bytes == 8)
                                        gma |= (cmd_gma_hi(s, 3)) << 32;
@@ -1129,6 +1151,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s,
                struct mi_display_flip_command_info *info)
 {
        struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+       struct intel_vgpu *vgpu = s->vgpu;
        u32 dword0 = cmd_val(s, 0);
        u32 dword1 = cmd_val(s, 1);
        u32 dword2 = cmd_val(s, 2);
@@ -1167,7 +1190,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s,
                break;
 
        default:
-               gvt_err("unknown plane code %d\n", plane);
+               gvt_vgpu_err("unknown plane code %d\n", plane);
                return -EINVAL;
        }
 
@@ -1274,25 +1297,26 @@ static int update_plane_mmio_from_mi_display_flip(
 static int cmd_handler_mi_display_flip(struct parser_exec_state *s)
 {
        struct mi_display_flip_command_info info;
+       struct intel_vgpu *vgpu = s->vgpu;
        int ret;
        int i;
        int len = cmd_length(s);
 
        ret = decode_mi_display_flip(s, &info);
        if (ret) {
-               gvt_err("fail to decode MI display flip command\n");
+               gvt_vgpu_err("fail to decode MI display flip command\n");
                return ret;
        }
 
        ret = check_mi_display_flip(s, &info);
        if (ret) {
-               gvt_err("invalid MI display flip command\n");
+               gvt_vgpu_err("invalid MI display flip command\n");
                return ret;
        }
 
        ret = update_plane_mmio_from_mi_display_flip(s, &info);
        if (ret) {
-               gvt_err("fail to update plane mmio\n");
+               gvt_vgpu_err("fail to update plane mmio\n");
                return ret;
        }
 
@@ -1350,7 +1374,8 @@ static inline int cmd_address_audit(struct parser_exec_state *s,
        int ret;
 
        if (op_size > max_surface_size) {
-               gvt_err("command address audit fail name %s\n", s->info->name);
+               gvt_vgpu_err("command address audit fail name %s\n",
+                       s->info->name);
                return -EINVAL;
        }
 
@@ -1367,7 +1392,7 @@ static inline int cmd_address_audit(struct parser_exec_state *s,
        }
        return 0;
 err:
-       gvt_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",
+       gvt_vgpu_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",
                        s->info->name, guest_gma, op_size);
 
        pr_err("cmd dump: ");
@@ -1412,8 +1437,10 @@ static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s)
 
 static inline int unexpected_cmd(struct parser_exec_state *s)
 {
-       gvt_err("vgpu%d: Unexpected %s in command buffer!\n",
-                       s->vgpu->id, s->info->name);
+       struct intel_vgpu *vgpu = s->vgpu;
+
+       gvt_vgpu_err("Unexpected %s in command buffer!\n", s->info->name);
+
        return -EINVAL;
 }
 
@@ -1516,7 +1543,7 @@ static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm,
        while (gma != end_gma) {
                gpa = intel_vgpu_gma_to_gpa(mm, gma);
                if (gpa == INTEL_GVT_INVALID_ADDR) {
-                       gvt_err("invalid gma address: %lx\n", gma);
+                       gvt_vgpu_err("invalid gma address: %lx\n", gma);
                        return -EFAULT;
                }
 
@@ -1557,6 +1584,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)
        uint32_t bb_size = 0;
        uint32_t cmd_len = 0;
        bool met_bb_end = false;
+       struct intel_vgpu *vgpu = s->vgpu;
        u32 cmd;
 
        /* get the start gm address of the batch buffer */
@@ -1565,7 +1593,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)
 
        info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
        if (info == NULL) {
-               gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+               gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",
                                cmd, get_opcode(cmd, s->ring_id));
                return -EINVAL;
        }
@@ -1574,7 +1602,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)
                                gma, gma + 4, &cmd);
                info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
                if (info == NULL) {
-                       gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+                       gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",
                                cmd, get_opcode(cmd, s->ring_id));
                        return -EINVAL;
                }
@@ -1599,6 +1627,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)
 static int perform_bb_shadow(struct parser_exec_state *s)
 {
        struct intel_shadow_bb_entry *entry_obj;
+       struct intel_vgpu *vgpu = s->vgpu;
        unsigned long gma = 0;
        uint32_t bb_size;
        void *dst = NULL;
@@ -1633,7 +1662,7 @@ static int perform_bb_shadow(struct parser_exec_state *s)
 
        ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false);
        if (ret) {
-               gvt_err("failed to set shadow batch to CPU\n");
+               gvt_vgpu_err("failed to set shadow batch to CPU\n");
                goto unmap_src;
        }
 
@@ -1645,7 +1674,7 @@ static int perform_bb_shadow(struct parser_exec_state *s)
                              gma, gma + bb_size,
                              dst);
        if (ret) {
-               gvt_err("fail to copy guest ring buffer\n");
+               gvt_vgpu_err("fail to copy guest ring buffer\n");
                goto unmap_src;
        }
 
@@ -1676,15 +1705,16 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)
 {
        bool second_level;
        int ret = 0;
+       struct intel_vgpu *vgpu = s->vgpu;
 
        if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) {
-               gvt_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n");
+               gvt_vgpu_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n");
                return -EINVAL;
        }
 
        second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1;
        if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) {
-               gvt_err("Jumping to 2nd level BB from RB is not allowed\n");
+               gvt_vgpu_err("Jumping to 2nd level BB from RB is not allowed\n");
                return -EINVAL;
        }
 
@@ -1702,7 +1732,7 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)
        if (batch_buffer_needs_scan(s)) {
                ret = perform_bb_shadow(s);
                if (ret < 0)
-                       gvt_err("invalid shadow batch buffer\n");
+                       gvt_vgpu_err("invalid shadow batch buffer\n");
        } else {
                /* emulate a batch buffer end to do return right */
                ret = cmd_handler_mi_batch_buffer_end(s);
@@ -2429,6 +2459,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)
        int ret = 0;
        cycles_t t0, t1, t2;
        struct parser_exec_state s_before_advance_custom;
+       struct intel_vgpu *vgpu = s->vgpu;
 
        t0 = get_cycles();
 
@@ -2436,7 +2467,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)
 
        info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
        if (info == NULL) {
-               gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+               gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",
                                cmd, get_opcode(cmd, s->ring_id));
                return -EINVAL;
        }
@@ -2452,7 +2483,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)
        if (info->handler) {
                ret = info->handler(s);
                if (ret < 0) {
-                       gvt_err("%s handler error\n", info->name);
+                       gvt_vgpu_err("%s handler error\n", info->name);
                        return ret;
                }
        }
@@ -2463,7 +2494,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)
        if (!(info->flag & F_IP_ADVANCE_CUSTOM)) {
                ret = cmd_advance_default(s);
                if (ret) {
-                       gvt_err("%s IP advance error\n", info->name);
+                       gvt_vgpu_err("%s IP advance error\n", info->name);
                        return ret;
                }
        }
@@ -2486,6 +2517,7 @@ static int command_scan(struct parser_exec_state *s,
 
        unsigned long gma_head, gma_tail, gma_bottom;
        int ret = 0;
+       struct intel_vgpu *vgpu = s->vgpu;
 
        gma_head = rb_start + rb_head;
        gma_tail = rb_start + rb_tail;
@@ -2497,7 +2529,7 @@ static int command_scan(struct parser_exec_state *s,
                if (s->buf_type == RING_BUFFER_INSTRUCTION) {
                        if (!(s->ip_gma >= rb_start) ||
                                !(s->ip_gma < gma_bottom)) {
-                               gvt_err("ip_gma %lx out of ring scope."
+                               gvt_vgpu_err("ip_gma %lx out of ring scope."
                                        "(base:0x%lx, bottom: 0x%lx)\n",
                                        s->ip_gma, rb_start,
                                        gma_bottom);
@@ -2505,7 +2537,7 @@ static int command_scan(struct parser_exec_state *s,
                                return -EINVAL;
                        }
                        if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) {
-                               gvt_err("ip_gma %lx out of range."
+                               gvt_vgpu_err("ip_gma %lx out of range."
                                        "base 0x%lx head 0x%lx tail 0x%lx\n",
                                        s->ip_gma, rb_start,
                                        rb_head, rb_tail);
@@ -2515,7 +2547,7 @@ static int command_scan(struct parser_exec_state *s,
                }
                ret = cmd_parser_exec(s);
                if (ret) {
-                       gvt_err("cmd parser error\n");
+                       gvt_vgpu_err("cmd parser error\n");
                        parser_exec_state_dump(s);
                        break;
                }
@@ -2639,7 +2671,7 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
                                gma_head, gma_top,
                                workload->shadow_ring_buffer_va);
                if (ret) {
-                       gvt_err("fail to copy guest ring buffer\n");
+                       gvt_vgpu_err("fail to copy guest ring buffer\n");
                        return ret;
                }
                copy_len = gma_top - gma_head;
@@ -2651,7 +2683,7 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
                        gma_head, gma_tail,
                        workload->shadow_ring_buffer_va + copy_len);
        if (ret) {
-               gvt_err("fail to copy guest ring buffer\n");
+               gvt_vgpu_err("fail to copy guest ring buffer\n");
                return ret;
        }
        ring->tail += workload->rb_len;
@@ -2662,16 +2694,17 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
 int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
 {
        int ret;
+       struct intel_vgpu *vgpu = workload->vgpu;
 
        ret = shadow_workload_ring_buffer(workload);
        if (ret) {
-               gvt_err("fail to shadow workload ring_buffer\n");
+               gvt_vgpu_err("fail to shadow workload ring_buffer\n");
                return ret;
        }
 
        ret = scan_workload(workload);
        if (ret) {
-               gvt_err("scan workload error\n");
+               gvt_vgpu_err("scan workload error\n");
                return ret;
        }
        return 0;
@@ -2681,6 +2714,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 {
        int ctx_size = wa_ctx->indirect_ctx.size;
        unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma;
+       struct intel_vgpu *vgpu = wa_ctx->workload->vgpu;
        struct drm_i915_gem_object *obj;
        int ret = 0;
        void *map;
@@ -2694,14 +2728,14 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        /* get the va of the shadow batch buffer */
        map = i915_gem_object_pin_map(obj, I915_MAP_WB);
        if (IS_ERR(map)) {
-               gvt_err("failed to vmap shadow indirect ctx\n");
+               gvt_vgpu_err("failed to vmap shadow indirect ctx\n");
                ret = PTR_ERR(map);
                goto put_obj;
        }
 
        ret = i915_gem_object_set_to_cpu_domain(obj, false);
        if (ret) {
-               gvt_err("failed to set shadow indirect ctx to CPU\n");
+               gvt_vgpu_err("failed to set shadow indirect ctx to CPU\n");
                goto unmap_src;
        }
 
@@ -2710,7 +2744,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)
                                guest_gma, guest_gma + ctx_size,
                                map);
        if (ret) {
-               gvt_err("fail to copy guest indirect ctx\n");
+               gvt_vgpu_err("fail to copy guest indirect ctx\n");
                goto unmap_src;
        }
 
@@ -2744,13 +2778,14 @@ static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 {
        int ret;
+       struct intel_vgpu *vgpu = wa_ctx->workload->vgpu;
 
        if (wa_ctx->indirect_ctx.size == 0)
                return 0;
 
        ret = shadow_indirect_ctx(wa_ctx);
        if (ret) {
-               gvt_err("fail to shadow indirect ctx\n");
+               gvt_vgpu_err("fail to shadow indirect ctx\n");
                return ret;
        }
 
@@ -2758,7 +2793,7 @@ int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 
        ret = scan_wa_ctx(wa_ctx);
        if (ret) {
-               gvt_err("scan wa ctx error\n");
+               gvt_vgpu_err("scan wa ctx error\n");
                return ret;
        }
 
index 68cba7bd980af8cb9a855ef3ff4a4c446947ebaf..b0cff4dc2684792271a5e648c889dbb5a4d04ac5 100644 (file)
 #define gvt_err(fmt, args...) \
        DRM_ERROR("gvt: "fmt, ##args)
 
+#define gvt_vgpu_err(fmt, args...)                                     \
+do {                                                                   \
+       if (IS_ERR_OR_NULL(vgpu))                                       \
+               DRM_DEBUG_DRIVER("gvt: "fmt, ##args);                   \
+       else                                                            \
+               DRM_DEBUG_DRIVER("gvt: vgpu %d: "fmt, vgpu->id, ##args);\
+} while (0)
+
 #define gvt_dbg_core(fmt, args...) \
        DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args)
 
index bda85dff7b2a998d68d1485479c9687eab206600..f1648fe5e5eaac09105b50c388cb63101b74bd2d 100644 (file)
@@ -52,16 +52,16 @@ static unsigned char edid_get_byte(struct intel_vgpu *vgpu)
        unsigned char chr = 0;
 
        if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) {
-               gvt_err("Driver tries to read EDID without proper sequence!\n");
+               gvt_vgpu_err("Driver tries to read EDID without proper sequence!\n");
                return 0;
        }
        if (edid->current_edid_read >= EDID_SIZE) {
-               gvt_err("edid_get_byte() exceeds the size of EDID!\n");
+               gvt_vgpu_err("edid_get_byte() exceeds the size of EDID!\n");
                return 0;
        }
 
        if (!edid->edid_available) {
-               gvt_err("Reading EDID but EDID is not available!\n");
+               gvt_vgpu_err("Reading EDID but EDID is not available!\n");
                return 0;
        }
 
@@ -72,7 +72,7 @@ static unsigned char edid_get_byte(struct intel_vgpu *vgpu)
                chr = edid_data->edid_block[edid->current_edid_read];
                edid->current_edid_read++;
        } else {
-               gvt_err("No EDID available during the reading?\n");
+               gvt_vgpu_err("No EDID available during the reading?\n");
        }
        return chr;
 }
@@ -223,7 +223,7 @@ static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                        vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE;
                        break;
                default:
-                       gvt_err("Unknown/reserved GMBUS cycle detected!\n");
+                       gvt_vgpu_err("Unknown/reserved GMBUS cycle detected!\n");
                        break;
                }
                /*
@@ -292,8 +292,7 @@ static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
                 */
        } else {
                memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
-               gvt_err("vgpu%d: warning: gmbus3 read with nothing returned\n",
-                               vgpu->id);
+               gvt_vgpu_err("warning: gmbus3 read with nothing returned\n");
        }
        return 0;
 }
index 46eb9fd3c03f6b2fdb19fec6550a5f4347038f88..f1f426a97aa9d43826010d7be90f6bffdbe59426 100644 (file)
@@ -172,6 +172,7 @@ static int emulate_execlist_ctx_schedule_out(
                struct intel_vgpu_execlist *execlist,
                struct execlist_ctx_descriptor_format *ctx)
 {
+       struct intel_vgpu *vgpu = execlist->vgpu;
        struct intel_vgpu_execlist_slot *running = execlist->running_slot;
        struct intel_vgpu_execlist_slot *pending = execlist->pending_slot;
        struct execlist_ctx_descriptor_format *ctx0 = &running->ctx[0];
@@ -183,7 +184,7 @@ static int emulate_execlist_ctx_schedule_out(
        gvt_dbg_el("schedule out context id %x\n", ctx->context_id);
 
        if (WARN_ON(!same_context(ctx, execlist->running_context))) {
-               gvt_err("schedule out context is not running context,"
+               gvt_vgpu_err("schedule out context is not running context,"
                                "ctx id %x running ctx id %x\n",
                                ctx->context_id,
                                execlist->running_context->context_id);
@@ -254,7 +255,7 @@ static struct intel_vgpu_execlist_slot *get_next_execlist_slot(
        status.udw = vgpu_vreg(vgpu, status_reg + 4);
 
        if (status.execlist_queue_full) {
-               gvt_err("virtual execlist slots are full\n");
+               gvt_vgpu_err("virtual execlist slots are full\n");
                return NULL;
        }
 
@@ -270,11 +271,12 @@ static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist,
 
        struct execlist_ctx_descriptor_format *ctx0, *ctx1;
        struct execlist_context_status_format status;
+       struct intel_vgpu *vgpu = execlist->vgpu;
 
        gvt_dbg_el("emulate schedule-in\n");
 
        if (!slot) {
-               gvt_err("no available execlist slot\n");
+               gvt_vgpu_err("no available execlist slot\n");
                return -EINVAL;
        }
 
@@ -375,7 +377,6 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)
 
                vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0);
                if (IS_ERR(vma)) {
-                       gvt_err("Cannot pin\n");
                        return;
                }
 
@@ -428,7 +429,6 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL,
                                       0, CACHELINE_BYTES, 0);
        if (IS_ERR(vma)) {
-               gvt_err("Cannot pin indirect ctx obj\n");
                return;
        }
 
@@ -561,6 +561,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)
 {
        struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;
        struct intel_vgpu_mm *mm;
+       struct intel_vgpu *vgpu = workload->vgpu;
        int page_table_level;
        u32 pdp[8];
 
@@ -569,7 +570,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)
        } else if (desc->addressing_mode == 3) { /* legacy 64 bit */
                page_table_level = 4;
        } else {
-               gvt_err("Advanced Context mode(SVM) is not supported!\n");
+               gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n");
                return -EINVAL;
        }
 
@@ -583,7 +584,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)
                mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT,
                                pdp, page_table_level, 0);
                if (IS_ERR(mm)) {
-                       gvt_err("fail to create mm object.\n");
+                       gvt_vgpu_err("fail to create mm object.\n");
                        return PTR_ERR(mm);
                }
        }
@@ -609,7 +610,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
        ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
                        (u32)((desc->lrca + 1) << GTT_PAGE_SHIFT));
        if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) {
-               gvt_err("invalid guest context LRCA: %x\n", desc->lrca);
+               gvt_vgpu_err("invalid guest context LRCA: %x\n", desc->lrca);
                return -EINVAL;
        }
 
@@ -724,8 +725,7 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)
                        continue;
 
                if (!desc[i]->privilege_access) {
-                       gvt_err("vgpu%d: unexpected GGTT elsp submission\n",
-                                       vgpu->id);
+                       gvt_vgpu_err("unexpected GGTT elsp submission\n");
                        return -EINVAL;
                }
 
@@ -735,15 +735,13 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)
        }
 
        if (!valid_desc_bitmap) {
-               gvt_err("vgpu%d: no valid desc in a elsp submission\n",
-                               vgpu->id);
+               gvt_vgpu_err("no valid desc in a elsp submission\n");
                return -EINVAL;
        }
 
        if (!test_bit(0, (void *)&valid_desc_bitmap) &&
                        test_bit(1, (void *)&valid_desc_bitmap)) {
-               gvt_err("vgpu%d: weird elsp submission, desc 0 is not valid\n",
-                               vgpu->id);
+               gvt_vgpu_err("weird elsp submission, desc 0 is not valid\n");
                return -EINVAL;
        }
 
@@ -752,8 +750,7 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)
                ret = submit_context(vgpu, ring_id, &valid_desc[i],
                                emulate_schedule_in);
                if (ret) {
-                       gvt_err("vgpu%d: fail to schedule workload\n",
-                                       vgpu->id);
+                       gvt_vgpu_err("fail to schedule workload\n");
                        return ret;
                }
                emulate_schedule_in = false;
index 6a5ff23ded907c475adff1151199add49c289994..da73127158241bb6659ab1c5c942c30c39fb2a56 100644 (file)
@@ -49,8 +49,8 @@ bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size)
 {
        if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size
                        && !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) {
-               gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n",
-                               vgpu->id, addr, size);
+               gvt_vgpu_err("invalid range gmadr 0x%llx size 0x%x\n",
+                               addr, size);
                return false;
        }
        return true;
@@ -430,7 +430,7 @@ static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
 
        mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
        if (mfn == INTEL_GVT_INVALID_ADDR) {
-               gvt_err("fail to translate gfn: 0x%lx\n", gfn);
+               gvt_vgpu_err("fail to translate gfn: 0x%lx\n", gfn);
                return -ENXIO;
        }
 
@@ -611,7 +611,7 @@ static inline int init_shadow_page(struct intel_vgpu *vgpu,
 
        daddr = dma_map_page(kdev, p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL);
        if (dma_mapping_error(kdev, daddr)) {
-               gvt_err("fail to map dma addr\n");
+               gvt_vgpu_err("fail to map dma addr\n");
                return -EINVAL;
        }
 
@@ -735,7 +735,7 @@ retry:
                if (reclaim_one_mm(vgpu->gvt))
                        goto retry;
 
-               gvt_err("fail to allocate ppgtt shadow page\n");
+               gvt_vgpu_err("fail to allocate ppgtt shadow page\n");
                return ERR_PTR(-ENOMEM);
        }
 
@@ -750,14 +750,14 @@ retry:
         */
        ret = init_shadow_page(vgpu, &spt->shadow_page, type);
        if (ret) {
-               gvt_err("fail to initialize shadow page for spt\n");
+               gvt_vgpu_err("fail to initialize shadow page for spt\n");
                goto err;
        }
 
        ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page,
                        gfn, ppgtt_write_protection_handler, NULL);
        if (ret) {
-               gvt_err("fail to initialize guest page for spt\n");
+               gvt_vgpu_err("fail to initialize guest page for spt\n");
                goto err;
        }
 
@@ -776,8 +776,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page(
        if (p)
                return shadow_page_to_ppgtt_spt(p);
 
-       gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n",
-                       vgpu->id, mfn);
+       gvt_vgpu_err("fail to find ppgtt shadow page: 0x%lx\n", mfn);
        return NULL;
 }
 
@@ -827,8 +826,8 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,
        }
        s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));
        if (!s) {
-               gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n",
-                               vgpu->id, ops->get_pfn(e));
+               gvt_vgpu_err("fail to find shadow page: mfn: 0x%lx\n",
+                               ops->get_pfn(e));
                return -ENXIO;
        }
        return ppgtt_invalidate_shadow_page(s);
@@ -836,6 +835,7 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,
 
 static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
 {
+       struct intel_vgpu *vgpu = spt->vgpu;
        struct intel_gvt_gtt_entry e;
        unsigned long index;
        int ret;
@@ -854,7 +854,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
 
        for_each_present_shadow_entry(spt, &e, index) {
                if (!gtt_type_is_pt(get_next_pt_type(e.type))) {
-                       gvt_err("GVT doesn't support pse bit for now\n");
+                       gvt_vgpu_err("GVT doesn't support pse bit for now\n");
                        return -EINVAL;
                }
                ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
@@ -868,8 +868,8 @@ release:
        ppgtt_free_shadow_page(spt);
        return 0;
 fail:
-       gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n",
-                       spt->vgpu->id, spt, e.val64, e.type);
+       gvt_vgpu_err("fail: shadow page %p shadow entry 0x%llx type %d\n",
+                       spt, e.val64, e.type);
        return ret;
 }
 
@@ -914,8 +914,8 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
        }
        return s;
 fail:
-       gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
-                       vgpu->id, s, we->val64, we->type);
+       gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
+                       s, we->val64, we->type);
        return ERR_PTR(ret);
 }
 
@@ -953,7 +953,7 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
 
        for_each_present_guest_entry(spt, &ge, i) {
                if (!gtt_type_is_pt(get_next_pt_type(ge.type))) {
-                       gvt_err("GVT doesn't support pse bit now\n");
+                       gvt_vgpu_err("GVT doesn't support pse bit now\n");
                        ret = -EINVAL;
                        goto fail;
                }
@@ -969,8 +969,8 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
        }
        return 0;
 fail:
-       gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
-                       vgpu->id, spt, ge.val64, ge.type);
+       gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
+                       spt, ge.val64, ge.type);
        return ret;
 }
 
@@ -999,7 +999,7 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
                struct intel_vgpu_ppgtt_spt *s =
                        ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e));
                if (!s) {
-                       gvt_err("fail to find guest page\n");
+                       gvt_vgpu_err("fail to find guest page\n");
                        ret = -ENXIO;
                        goto fail;
                }
@@ -1011,8 +1011,8 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
        ppgtt_set_shadow_entry(spt, &e, index);
        return 0;
 fail:
-       gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
-                       vgpu->id, spt, e.val64, e.type);
+       gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
+                       spt, e.val64, e.type);
        return ret;
 }
 
@@ -1046,8 +1046,8 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,
        }
        return 0;
 fail:
-       gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id,
-                       spt, we->val64, we->type);
+       gvt_vgpu_err("fail: spt %p guest entry 0x%llx type %d\n",
+               spt, we->val64, we->type);
        return ret;
 }
 
@@ -1250,8 +1250,8 @@ static int ppgtt_handle_guest_write_page_table(
        }
        return 0;
 fail:
-       gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n",
-                       vgpu->id, spt, we->val64, we->type);
+       gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d.\n",
+                       spt, we->val64, we->type);
        return ret;
 }
 
@@ -1493,7 +1493,7 @@ static int shadow_mm(struct intel_vgpu_mm *mm)
 
                spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
                if (IS_ERR(spt)) {
-                       gvt_err("fail to populate guest root pointer\n");
+                       gvt_vgpu_err("fail to populate guest root pointer\n");
                        ret = PTR_ERR(spt);
                        goto fail;
                }
@@ -1566,7 +1566,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
 
        ret = gtt->mm_alloc_page_table(mm);
        if (ret) {
-               gvt_err("fail to allocate page table for mm\n");
+               gvt_vgpu_err("fail to allocate page table for mm\n");
                goto fail;
        }
 
@@ -1584,7 +1584,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
        }
        return mm;
 fail:
-       gvt_err("fail to create mm\n");
+       gvt_vgpu_err("fail to create mm\n");
        if (mm)
                intel_gvt_mm_unreference(mm);
        return ERR_PTR(ret);
@@ -1760,7 +1760,7 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
                        mm->page_table_level, gma, gpa);
        return gpa;
 err:
-       gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma);
+       gvt_vgpu_err("invalid mm type: %d gma %lx\n", mm->type, gma);
        return INTEL_GVT_INVALID_ADDR;
 }
 
@@ -1836,8 +1836,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
        if (ops->test_present(&e)) {
                ret = gtt_entry_p2m(vgpu, &e, &m);
                if (ret) {
-                       gvt_err("vgpu%d: fail to translate guest gtt entry\n",
-                                       vgpu->id);
+                       gvt_vgpu_err("fail to translate guest gtt entry\n");
                        return ret;
                }
        } else {
@@ -1893,14 +1892,14 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
 
        scratch_pt = (void *)get_zeroed_page(GFP_KERNEL);
        if (!scratch_pt) {
-               gvt_err("fail to allocate scratch page\n");
+               gvt_vgpu_err("fail to allocate scratch page\n");
                return -ENOMEM;
        }
 
        daddr = dma_map_page(dev, virt_to_page(scratch_pt), 0,
                        4096, PCI_DMA_BIDIRECTIONAL);
        if (dma_mapping_error(dev, daddr)) {
-               gvt_err("fail to dmamap scratch_pt\n");
+               gvt_vgpu_err("fail to dmamap scratch_pt\n");
                __free_page(virt_to_page(scratch_pt));
                return -ENOMEM;
        }
@@ -2003,7 +2002,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
        ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
                        NULL, 1, 0);
        if (IS_ERR(ggtt_mm)) {
-               gvt_err("fail to create mm for ggtt.\n");
+               gvt_vgpu_err("fail to create mm for ggtt.\n");
                return PTR_ERR(ggtt_mm);
        }
 
@@ -2076,7 +2075,6 @@ static int setup_spt_oos(struct intel_gvt *gvt)
        for (i = 0; i < preallocated_oos_pages; i++) {
                oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL);
                if (!oos_page) {
-                       gvt_err("fail to pre-allocate oos page\n");
                        ret = -ENOMEM;
                        goto fail;
                }
@@ -2166,7 +2164,7 @@ int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
                mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT,
                                pdp, page_table_level, 0);
                if (IS_ERR(mm)) {
-                       gvt_err("fail to create mm\n");
+                       gvt_vgpu_err("fail to create mm\n");
                        return PTR_ERR(mm);
                }
        }
@@ -2196,7 +2194,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
 
        mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
        if (!mm) {
-               gvt_err("fail to find ppgtt instance.\n");
+               gvt_vgpu_err("fail to find ppgtt instance.\n");
                return -EINVAL;
        }
        intel_gvt_mm_unreference(mm);
index 23791920ced1eed3e7aa1566b843a464fcfe3b29..6dfc48b63b718b4c4e6f5c62794db5ce279b18a4 100644 (file)
@@ -162,7 +162,6 @@ struct intel_vgpu {
        atomic_t running_workload_num;
        DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
        struct i915_gem_context *shadow_ctx;
-       struct notifier_block shadow_ctx_notifier_block;
 
 #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
        struct {
@@ -233,6 +232,7 @@ struct intel_gvt {
        struct intel_gvt_gtt gtt;
        struct intel_gvt_opregion opregion;
        struct intel_gvt_workload_scheduler scheduler;
+       struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
        DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
        struct intel_vgpu_type *types;
        unsigned int num_types;
index 8e43395c748a15cc60f6e80d7b43f8b28fbce4aa..eaff45d417e8a0a5eeb77f6dc28b6eef98b4df4a 100644 (file)
@@ -181,11 +181,9 @@ static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu,
                                        GVT_FAILSAFE_UNSUPPORTED_GUEST);
 
                if (!vgpu->mmio.disable_warn_untrack) {
-                       gvt_err("vgpu%d: found oob fence register access\n",
-                                       vgpu->id);
-                       gvt_err("vgpu%d: total fence %d, access fence %d\n",
-                                       vgpu->id, vgpu_fence_sz(vgpu),
-                                       fence_num);
+                       gvt_vgpu_err("found oob fence register access\n");
+                       gvt_vgpu_err("total fence %d, access fence %d\n",
+                                       vgpu_fence_sz(vgpu), fence_num);
                }
                memset(p_data, 0, bytes);
                return -EINVAL;
@@ -249,7 +247,7 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu,
                        break;
                default:
                        /*should not hit here*/
-                       gvt_err("invalid forcewake offset 0x%x\n", offset);
+                       gvt_vgpu_err("invalid forcewake offset 0x%x\n", offset);
                        return -EINVAL;
                }
        } else {
@@ -530,7 +528,7 @@ static int check_fdi_rx_train_status(struct intel_vgpu *vgpu,
                fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_2;
                fdi_iir_check_bits = FDI_RX_SYMBOL_LOCK;
        } else {
-               gvt_err("Invalid train pattern %d\n", train_pattern);
+               gvt_vgpu_err("Invalid train pattern %d\n", train_pattern);
                return -EINVAL;
        }
 
@@ -588,7 +586,7 @@ static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu,
        else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX)
                index = FDI_RX_IMR_TO_PIPE(offset);
        else {
-               gvt_err("Unsupport registers %x\n", offset);
+               gvt_vgpu_err("Unsupport registers %x\n", offset);
                return -EINVAL;
        }
 
@@ -818,7 +816,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
        u32 data;
 
        if (!dpy_is_valid_port(port_index)) {
-               gvt_err("GVT(%d): Unsupported DP port access!\n", vgpu->id);
+               gvt_vgpu_err("Unsupported DP port access!\n");
                return 0;
        }
 
@@ -1016,8 +1014,7 @@ static void write_virtual_sbi_register(struct intel_vgpu *vgpu,
 
        if (i == num) {
                if (num == SBI_REG_MAX) {
-                       gvt_err("vgpu%d: SBI caching meets maximum limits\n",
-                                       vgpu->id);
+                       gvt_vgpu_err("SBI caching meets maximum limits\n");
                        return;
                }
                display->sbi.number++;
@@ -1097,7 +1094,7 @@ static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
                break;
        }
        if (invalid_read)
-               gvt_err("invalid pvinfo read: [%x:%x] = %x\n",
+               gvt_vgpu_err("invalid pvinfo read: [%x:%x] = %x\n",
                                offset, bytes, *(u32 *)p_data);
        vgpu->pv_notified = true;
        return 0;
@@ -1125,7 +1122,7 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
        case 1: /* Remove this in guest driver. */
                break;
        default:
-               gvt_err("Invalid PV notification %d\n", notification);
+               gvt_vgpu_err("Invalid PV notification %d\n", notification);
        }
        return ret;
 }
@@ -1181,7 +1178,7 @@ static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                enter_failsafe_mode(vgpu, GVT_FAILSAFE_INSUFFICIENT_RESOURCE);
                break;
        default:
-               gvt_err("invalid pvinfo write offset %x bytes %x data %x\n",
+               gvt_vgpu_err("invalid pvinfo write offset %x bytes %x data %x\n",
                                offset, bytes, data);
                break;
        }
@@ -1415,7 +1412,8 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
        if (execlist->elsp_dwords.index == 3) {
                ret = intel_vgpu_submit_execlist(vgpu, ring_id);
                if(ret)
-                       gvt_err("fail submit workload on ring %d\n", ring_id);
+                       gvt_vgpu_err("fail submit workload on ring %d\n",
+                               ring_id);
        }
 
        ++execlist->elsp_dwords.index;
@@ -2988,3 +2986,20 @@ int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
        write_vreg(vgpu, offset, p_data, bytes);
        return 0;
 }
+
+/**
+ * intel_gvt_in_force_nonpriv_whitelist - if a mmio is in whitelist to be
+ * force-nopriv register
+ *
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ * Returns:
+ * True if the register is in force-nonpriv whitelist;
+ * False if outside;
+ */
+bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt,
+                                         unsigned int offset)
+{
+       return in_whitelist(offset);
+}
index 84d801638edece195bad5b659c5d739c1afcf0fc..1ea3eb270de8f38d32b4c44ffa3e5cc420a2f8b8 100644 (file)
@@ -426,7 +426,7 @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
 
 static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 {
-       struct intel_vgpu *vgpu;
+       struct intel_vgpu *vgpu = NULL;
        struct intel_vgpu_type *type;
        struct device *pdev;
        void *gvt;
@@ -437,7 +437,7 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 
        type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
        if (!type) {
-               gvt_err("failed to find type %s to create\n",
+               gvt_vgpu_err("failed to find type %s to create\n",
                                                kobject_name(kobj));
                ret = -EINVAL;
                goto out;
@@ -446,7 +446,7 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
        vgpu = intel_gvt_ops->vgpu_create(gvt, type);
        if (IS_ERR_OR_NULL(vgpu)) {
                ret = vgpu == NULL ? -EFAULT : PTR_ERR(vgpu);
-               gvt_err("failed to create intel vgpu: %d\n", ret);
+               gvt_vgpu_err("failed to create intel vgpu: %d\n", ret);
                goto out;
        }
 
@@ -526,7 +526,8 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, &events,
                                &vgpu->vdev.iommu_notifier);
        if (ret != 0) {
-               gvt_err("vfio_register_notifier for iommu failed: %d\n", ret);
+               gvt_vgpu_err("vfio_register_notifier for iommu failed: %d\n",
+                       ret);
                goto out;
        }
 
@@ -534,7 +535,8 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, &events,
                                &vgpu->vdev.group_notifier);
        if (ret != 0) {
-               gvt_err("vfio_register_notifier for group failed: %d\n", ret);
+               gvt_vgpu_err("vfio_register_notifier for group failed: %d\n",
+                       ret);
                goto undo_iommu;
        }
 
@@ -635,7 +637,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
 
 
        if (index >= VFIO_PCI_NUM_REGIONS) {
-               gvt_err("invalid index: %u\n", index);
+               gvt_vgpu_err("invalid index: %u\n", index);
                return -EINVAL;
        }
 
@@ -669,7 +671,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
        case VFIO_PCI_VGA_REGION_INDEX:
        case VFIO_PCI_ROM_REGION_INDEX:
        default:
-               gvt_err("unsupported region: %u\n", index);
+               gvt_vgpu_err("unsupported region: %u\n", index);
        }
 
        return ret == 0 ? count : ret;
@@ -861,7 +863,7 @@ static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,
 
                trigger = eventfd_ctx_fdget(fd);
                if (IS_ERR(trigger)) {
-                       gvt_err("eventfd_ctx_fdget failed\n");
+                       gvt_vgpu_err("eventfd_ctx_fdget failed\n");
                        return PTR_ERR(trigger);
                }
                vgpu->vdev.msi_trigger = trigger;
@@ -1120,7 +1122,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
                        ret = vfio_set_irqs_validate_and_prepare(&hdr, max,
                                                VFIO_PCI_NUM_IRQS, &data_size);
                        if (ret) {
-                               gvt_err("intel:vfio_set_irqs_validate_and_prepare failed\n");
+                               gvt_vgpu_err("intel:vfio_set_irqs_validate_and_prepare failed\n");
                                return -EINVAL;
                        }
                        if (data_size) {
@@ -1310,7 +1312,7 @@ static int kvmgt_guest_init(struct mdev_device *mdev)
 
        kvm = vgpu->vdev.kvm;
        if (!kvm || kvm->mm != current->mm) {
-               gvt_err("KVM is required to use Intel vGPU\n");
+               gvt_vgpu_err("KVM is required to use Intel vGPU\n");
                return -ESRCH;
        }
 
@@ -1337,8 +1339,10 @@ static int kvmgt_guest_init(struct mdev_device *mdev)
 
 static bool kvmgt_guest_exit(struct kvmgt_guest_info *info)
 {
+       struct intel_vgpu *vgpu = info->vgpu;
+
        if (!info) {
-               gvt_err("kvmgt_guest_info invalid\n");
+               gvt_vgpu_err("kvmgt_guest_info invalid\n");
                return false;
        }
 
@@ -1383,12 +1387,14 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
        unsigned long iova, pfn;
        struct kvmgt_guest_info *info;
        struct device *dev;
+       struct intel_vgpu *vgpu;
        int rc;
 
        if (!handle_valid(handle))
                return INTEL_GVT_INVALID_ADDR;
 
        info = (struct kvmgt_guest_info *)handle;
+       vgpu = info->vgpu;
        iova = gvt_cache_find(info->vgpu, gfn);
        if (iova != INTEL_GVT_INVALID_ADDR)
                return iova;
@@ -1397,13 +1403,14 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
        dev = mdev_dev(info->vgpu->vdev.mdev);
        rc = vfio_pin_pages(dev, &gfn, 1, IOMMU_READ | IOMMU_WRITE, &pfn);
        if (rc != 1) {
-               gvt_err("vfio_pin_pages failed for gfn 0x%lx: %d\n", gfn, rc);
+               gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx: %d\n",
+                       gfn, rc);
                return INTEL_GVT_INVALID_ADDR;
        }
        /* transfer to host iova for GFX to use DMA */
        rc = gvt_dma_map_iova(info->vgpu, pfn, &iova);
        if (rc) {
-               gvt_err("gvt_dma_map_iova failed for gfn: 0x%lx\n", gfn);
+               gvt_vgpu_err("gvt_dma_map_iova failed for gfn: 0x%lx\n", gfn);
                vfio_unpin_pages(dev, &gfn, 1);
                return INTEL_GVT_INVALID_ADDR;
        }
@@ -1417,7 +1424,7 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
 {
        struct kvmgt_guest_info *info;
        struct kvm *kvm;
-       int ret;
+       int idx, ret;
        bool kthread = current->mm == NULL;
 
        if (!handle_valid(handle))
@@ -1429,8 +1436,10 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
        if (kthread)
                use_mm(kvm->mm);
 
+       idx = srcu_read_lock(&kvm->srcu);
        ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
                      kvm_read_guest(kvm, gpa, buf, len);
+       srcu_read_unlock(&kvm->srcu, idx);
 
        if (kthread)
                unuse_mm(kvm->mm);
index 60b698cb836592747cf354840e930211230c1622..1ba3bdb093416674c2f44014942971bcdcd8ea9e 100644 (file)
@@ -142,10 +142,10 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
                        ret = intel_gvt_hypervisor_read_gpa(vgpu, pa,
                                        p_data, bytes);
                        if (ret) {
-                               gvt_err("vgpu%d: guest page read error %d, "
+                               gvt_vgpu_err("guest page read error %d, "
                                        "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
-                                       vgpu->id, ret,
-                                       gp->gfn, pa, *(u32 *)p_data, bytes);
+                                       ret, gp->gfn, pa, *(u32 *)p_data,
+                                       bytes);
                        }
                        mutex_unlock(&gvt->lock);
                        return ret;
@@ -200,14 +200,13 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
                ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
 
                if (!vgpu->mmio.disable_warn_untrack) {
-                       gvt_err("vgpu%d: read untracked MMIO %x(%dB) val %x\n",
-                               vgpu->id, offset, bytes, *(u32 *)p_data);
+                       gvt_vgpu_err("read untracked MMIO %x(%dB) val %x\n",
+                               offset, bytes, *(u32 *)p_data);
 
                        if (offset == 0x206c) {
-                               gvt_err("------------------------------------------\n");
-                               gvt_err("vgpu%d: likely triggers a gfx reset\n",
-                                       vgpu->id);
-                               gvt_err("------------------------------------------\n");
+                               gvt_vgpu_err("------------------------------------------\n");
+                               gvt_vgpu_err("likely triggers a gfx reset\n");
+                               gvt_vgpu_err("------------------------------------------\n");
                                vgpu->mmio.disable_warn_untrack = true;
                        }
                }
@@ -220,8 +219,8 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
        mutex_unlock(&gvt->lock);
        return 0;
 err:
-       gvt_err("vgpu%d: fail to emulate MMIO read %08x len %d\n",
-                       vgpu->id, offset, bytes);
+       gvt_vgpu_err("fail to emulate MMIO read %08x len %d\n",
+                       offset, bytes);
        mutex_unlock(&gvt->lock);
        return ret;
 }
@@ -259,10 +258,11 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
                if (gp) {
                        ret = gp->handler(gp, pa, p_data, bytes);
                        if (ret) {
-                               gvt_err("vgpu%d: guest page write error %d, "
-                                       "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
-                                       vgpu->id, ret,
-                                       gp->gfn, pa, *(u32 *)p_data, bytes);
+                               gvt_err("guest page write error %d, "
+                                       "gfn 0x%lx, pa 0x%llx, "
+                                       "var 0x%x, len %d\n",
+                                       ret, gp->gfn, pa,
+                                       *(u32 *)p_data, bytes);
                        }
                        mutex_unlock(&gvt->lock);
                        return ret;
@@ -329,8 +329,8 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
 
                        /* all register bits are RO. */
                        if (ro_mask == ~(u64)0) {
-                               gvt_err("vgpu%d: try to write RO reg %x\n",
-                                               vgpu->id, offset);
+                               gvt_vgpu_err("try to write RO reg %x\n",
+                                       offset);
                                ret = 0;
                                goto out;
                        }
@@ -360,8 +360,8 @@ out:
        mutex_unlock(&gvt->lock);
        return 0;
 err:
-       gvt_err("vgpu%d: fail to emulate MMIO write %08x len %d\n",
-                       vgpu->id, offset, bytes);
+       gvt_vgpu_err("fail to emulate MMIO write %08x len %d\n", offset,
+                    bytes);
        mutex_unlock(&gvt->lock);
        return ret;
 }
index 3bc620f56f351e774dc8658c9f06c79d0b24446b..a3a027025cd0a40f9543e6ee76b385a4ad761dcc 100644 (file)
@@ -107,4 +107,7 @@ int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
                                 void *p_data, unsigned int bytes);
 int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                                  void *p_data, unsigned int bytes);
+
+bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt,
+                                         unsigned int offset);
 #endif
index 5d1caf9daba9bdc82ed90018a6d31ec23825e680..311799136d7f6e9e2fd96537da3c69918d7258ee 100644 (file)
@@ -67,14 +67,15 @@ static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
                mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu)->va
                        + i * PAGE_SIZE);
                if (mfn == INTEL_GVT_INVALID_ADDR) {
-                       gvt_err("fail to get MFN from VA\n");
+                       gvt_vgpu_err("fail to get MFN from VA\n");
                        return -EINVAL;
                }
                ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,
                                vgpu_opregion(vgpu)->gfn[i],
                                mfn, 1, map);
                if (ret) {
-                       gvt_err("fail to map GFN to MFN, errno: %d\n", ret);
+                       gvt_vgpu_err("fail to map GFN to MFN, errno: %d\n",
+                               ret);
                        return ret;
                }
        }
@@ -287,7 +288,7 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
        parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;
 
        if (!(swsci & SWSCI_SCI_SELECT)) {
-               gvt_err("vgpu%d: requesting SMI service\n", vgpu->id);
+               gvt_vgpu_err("requesting SMI service\n");
                return 0;
        }
        /* ignore non 0->1 trasitions */
@@ -300,9 +301,8 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
        func = GVT_OPREGION_FUNC(*scic);
        subfunc = GVT_OPREGION_SUBFUNC(*scic);
        if (!querying_capabilities(*scic)) {
-               gvt_err("vgpu%d: requesting runtime service: func \"%s\","
+               gvt_vgpu_err("requesting runtime service: func \"%s\","
                                " subfunc \"%s\"\n",
-                               vgpu->id,
                                opregion_func_name(func),
                                opregion_subfunc_name(subfunc));
                /*
index 73f052a4f4244d9c31ce8ad875978a50f8d084c4..95ee091ce085de3bb2b2b034367213f9eeac6f2c 100644 (file)
@@ -167,7 +167,7 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)
        I915_WRITE_FW(reg, 0x1);
 
        if (wait_for_atomic((I915_READ_FW(reg) == 0), 50))
-               gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id);
+               gvt_vgpu_err("timeout in invalidate ring (%d) tlb\n", ring_id);
        else
                vgpu_vreg(vgpu, regs[ring_id]) = 0;
 
index 06c9584ac5f0333c28d628d797686b82d8f82806..34b9acdf34791c84170cd6c96203a5b84f860b77 100644 (file)
@@ -101,7 +101,7 @@ struct tbs_sched_data {
        struct list_head runq_head;
 };
 
-#define GVT_DEFAULT_TIME_SLICE (1 * HZ / 1000)
+#define GVT_DEFAULT_TIME_SLICE (msecs_to_jiffies(1))
 
 static void tbs_sched_func(struct work_struct *work)
 {
@@ -223,7 +223,7 @@ static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
                return;
 
        list_add_tail(&vgpu_data->list, &sched_data->runq_head);
-       schedule_delayed_work(&sched_data->work, sched_data->period);
+       schedule_delayed_work(&sched_data->work, 0);
 }
 
 static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu)
index d3a56c9490257d4deeb4dfa3bbfa0a8e10d2bb47..c4353ed86d4b30da172c3afc8fcbaf251a582437 100644 (file)
@@ -84,7 +84,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
                                (u32)((workload->ctx_desc.lrca + i) <<
                                GTT_PAGE_SHIFT));
                if (context_gpa == INTEL_GVT_INVALID_ADDR) {
-                       gvt_err("Invalid guest context descriptor\n");
+                       gvt_vgpu_err("Invalid guest context descriptor\n");
                        return -EINVAL;
                }
 
@@ -130,12 +130,10 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
 static int shadow_context_status_change(struct notifier_block *nb,
                unsigned long action, void *data)
 {
-       struct intel_vgpu *vgpu = container_of(nb,
-                       struct intel_vgpu, shadow_ctx_notifier_block);
-       struct drm_i915_gem_request *req =
-               (struct drm_i915_gem_request *)data;
-       struct intel_gvt_workload_scheduler *scheduler =
-               &vgpu->gvt->scheduler;
+       struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data;
+       struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
+                               shadow_ctx_notifier_block[req->engine->id]);
+       struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
        struct intel_vgpu_workload *workload =
                scheduler->current_workload[req->engine->id];
 
@@ -175,7 +173,9 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
        int ring_id = workload->ring_id;
        struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
        struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
+       struct intel_engine_cs *engine = dev_priv->engine[ring_id];
        struct drm_i915_gem_request *rq;
+       struct intel_vgpu *vgpu = workload->vgpu;
        int ret;
 
        gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n",
@@ -187,9 +187,24 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
 
        mutex_lock(&dev_priv->drm.struct_mutex);
 
+       /* pin shadow context by gvt even the shadow context will be pinned
+        * when i915 alloc request. That is because gvt will update the guest
+        * context from shadow context when workload is completed, and at that
+        * moment, i915 may already unpined the shadow context to make the
+        * shadow_ctx pages invalid. So gvt need to pin itself. After update
+        * the guest context, gvt can unpin the shadow_ctx safely.
+        */
+       ret = engine->context_pin(engine, shadow_ctx);
+       if (ret) {
+               gvt_vgpu_err("fail to pin shadow context\n");
+               workload->status = ret;
+               mutex_unlock(&dev_priv->drm.struct_mutex);
+               return ret;
+       }
+
        rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx);
        if (IS_ERR(rq)) {
-               gvt_err("fail to allocate gem request\n");
+               gvt_vgpu_err("fail to allocate gem request\n");
                ret = PTR_ERR(rq);
                goto out;
        }
@@ -202,9 +217,12 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
        if (ret)
                goto out;
 
-       ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx);
-       if (ret)
-               goto out;
+       if ((workload->ring_id == RCS) &&
+           (workload->wa_ctx.indirect_ctx.size != 0)) {
+               ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx);
+               if (ret)
+                       goto out;
+       }
 
        ret = populate_shadow_context(workload);
        if (ret)
@@ -227,6 +245,9 @@ out:
 
        if (!IS_ERR_OR_NULL(rq))
                i915_add_request_no_flush(rq);
+       else
+               engine->context_unpin(engine, shadow_ctx);
+
        mutex_unlock(&dev_priv->drm.struct_mutex);
        return ret;
 }
@@ -322,7 +343,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload)
                                (u32)((workload->ctx_desc.lrca + i) <<
                                        GTT_PAGE_SHIFT));
                if (context_gpa == INTEL_GVT_INVALID_ADDR) {
-                       gvt_err("invalid guest context descriptor\n");
+                       gvt_vgpu_err("invalid guest context descriptor\n");
                        return;
                }
 
@@ -376,6 +397,10 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
         * For the workload w/o request, directly complete the workload.
         */
        if (workload->req) {
+               struct drm_i915_private *dev_priv =
+                       workload->vgpu->gvt->dev_priv;
+               struct intel_engine_cs *engine =
+                       dev_priv->engine[workload->ring_id];
                wait_event(workload->shadow_ctx_status_wq,
                           !atomic_read(&workload->shadow_ctx_active));
 
@@ -388,6 +413,10 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
                                         INTEL_GVT_EVENT_MAX)
                                intel_vgpu_trigger_virtual_event(vgpu, event);
                }
+               mutex_lock(&dev_priv->drm.struct_mutex);
+               /* unpin shadow ctx as the shadow_ctx update is done */
+               engine->context_unpin(engine, workload->vgpu->shadow_ctx);
+               mutex_unlock(&dev_priv->drm.struct_mutex);
        }
 
        gvt_dbg_sched("ring id %d complete workload %p status %d\n",
@@ -417,6 +446,7 @@ static int workload_thread(void *priv)
        int ring_id = p->ring_id;
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
        struct intel_vgpu_workload *workload = NULL;
+       struct intel_vgpu *vgpu = NULL;
        int ret;
        bool need_force_wake = IS_SKYLAKE(gvt->dev_priv);
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
@@ -459,25 +489,14 @@ static int workload_thread(void *priv)
                mutex_unlock(&gvt->lock);
 
                if (ret) {
-                       gvt_err("fail to dispatch workload, skip\n");
+                       vgpu = workload->vgpu;
+                       gvt_vgpu_err("fail to dispatch workload, skip\n");
                        goto complete;
                }
 
                gvt_dbg_sched("ring id %d wait workload %p\n",
                                workload->ring_id, workload);
-retry:
-               i915_wait_request(workload->req,
-                                        0, MAX_SCHEDULE_TIMEOUT);
-               /* I915 has replay mechanism and a request will be replayed
-                * if there is i915 reset. So the seqno will be updated anyway.
-                * If the seqno is not updated yet after waiting, which means
-                * the replay may still be in progress and we can wait again.
-                */
-               if (!i915_gem_request_completed(workload->req)) {
-                       gvt_dbg_sched("workload %p not completed, wait again\n",
-                                       workload);
-                       goto retry;
-               }
+               i915_wait_request(workload->req, 0, MAX_SCHEDULE_TIMEOUT);
 
 complete:
                gvt_dbg_sched("will complete workload %p, status: %d\n",
@@ -513,15 +532,16 @@ void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
 void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
 {
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
-       int i;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id i;
 
        gvt_dbg_core("clean workload scheduler\n");
 
-       for (i = 0; i < I915_NUM_ENGINES; i++) {
-               if (scheduler->thread[i]) {
-                       kthread_stop(scheduler->thread[i]);
-                       scheduler->thread[i] = NULL;
-               }
+       for_each_engine(engine, gvt->dev_priv, i) {
+               atomic_notifier_chain_unregister(
+                                       &engine->context_status_notifier,
+                                       &gvt->shadow_ctx_notifier_block[i]);
+               kthread_stop(scheduler->thread[i]);
        }
 }
 
@@ -529,18 +549,15 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)
 {
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
        struct workload_thread_param *param = NULL;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id i;
        int ret;
-       int i;
 
        gvt_dbg_core("init workload scheduler\n");
 
        init_waitqueue_head(&scheduler->workload_complete_wq);
 
-       for (i = 0; i < I915_NUM_ENGINES; i++) {
-               /* check ring mask at init time */
-               if (!HAS_ENGINE(gvt->dev_priv, i))
-                       continue;
-
+       for_each_engine(engine, gvt->dev_priv, i) {
                init_waitqueue_head(&scheduler->waitq[i]);
 
                param = kzalloc(sizeof(*param), GFP_KERNEL);
@@ -559,6 +576,11 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)
                        ret = PTR_ERR(scheduler->thread[i]);
                        goto err;
                }
+
+               gvt->shadow_ctx_notifier_block[i].notifier_call =
+                                       shadow_context_status_change;
+               atomic_notifier_chain_register(&engine->context_status_notifier,
+                                       &gvt->shadow_ctx_notifier_block[i]);
        }
        return 0;
 err:
@@ -570,9 +592,6 @@ err:
 
 void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu)
 {
-       atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier,
-                       &vgpu->shadow_ctx_notifier_block);
-
        i915_gem_context_put_unlocked(vgpu->shadow_ctx);
 }
 
@@ -587,10 +606,5 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu)
 
        vgpu->shadow_ctx->engine[RCS].initialised = true;
 
-       vgpu->shadow_ctx_notifier_block.notifier_call =
-               shadow_context_status_change;
-
-       atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier,
-                                      &vgpu->shadow_ctx_notifier_block);
        return 0;
 }
index e703556eba999a95fd1a728538f6412db28068ae..1c75402a59c1377e7abd410f2dc58dcec0df7094 100644 (file)
@@ -248,6 +248,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_IRQ_ACTIVE:
        case I915_PARAM_ALLOW_BATCHBUFFER:
        case I915_PARAM_LAST_DISPATCH:
+       case I915_PARAM_HAS_EXEC_CONSTANTS:
                /* Reject all old ums/dri params. */
                return -ENODEV;
        case I915_PARAM_CHIPSET_ID:
@@ -274,9 +275,6 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_BSD2:
                value = !!dev_priv->engine[VCS2];
                break;
-       case I915_PARAM_HAS_EXEC_CONSTANTS:
-               value = INTEL_GEN(dev_priv) >= 4;
-               break;
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev_priv);
                break;
@@ -1788,7 +1786,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
                goto error;
        }
 
-       i915_gem_reset_finish(dev_priv);
+       i915_gem_reset(dev_priv);
        intel_overlay_reset(dev_priv);
 
        /* Ok, now get things going again... */
@@ -1814,6 +1812,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
        i915_queue_hangcheck(dev_priv);
 
 wakeup:
+       i915_gem_reset_finish(dev_priv);
        enable_irq(dev_priv->drm.irq);
        wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS);
        return;
index 0a4b42d313912c3c5b56a449cfac33e63afeb16e..1e53c31b6826ec996b2d153e1dd32232b77dd9d7 100644 (file)
@@ -293,6 +293,7 @@ enum plane_id {
        PLANE_PRIMARY,
        PLANE_SPRITE0,
        PLANE_SPRITE1,
+       PLANE_SPRITE2,
        PLANE_CURSOR,
        I915_MAX_PLANES,
 };
@@ -1324,7 +1325,7 @@ struct intel_gen6_power_mgmt {
        unsigned boosts;
 
        /* manual wa residency calculations */
-       struct intel_rps_ei up_ei, down_ei;
+       struct intel_rps_ei ei;
 
        /*
         * Protects RPS/RC6 register access and PCU communication.
@@ -2063,8 +2064,6 @@ struct drm_i915_private {
 
        const struct intel_device_info info;
 
-       int relative_constants_mode;
-
        void __iomem *regs;
 
        struct intel_uncore uncore;
@@ -3341,6 +3340,7 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
 }
 
 int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
+void i915_gem_reset(struct drm_i915_private *dev_priv);
 void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
 void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
 void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
index 6908123162d17cd998c1e7f0bf54a27064e67588..67b1fc5a03313b80bc9459543b8dec3743ea953b 100644 (file)
@@ -1434,6 +1434,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 
        trace_i915_gem_object_pwrite(obj, args->offset, args->size);
 
+       ret = -ENODEV;
+       if (obj->ops->pwrite)
+               ret = obj->ops->pwrite(obj, args);
+       if (ret != -ENODEV)
+               goto err;
+
        ret = i915_gem_object_wait(obj,
                                   I915_WAIT_INTERRUPTIBLE |
                                   I915_WAIT_ALL,
@@ -2119,6 +2125,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
         */
        shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
        obj->mm.madv = __I915_MADV_PURGED;
+       obj->mm.pages = ERR_PTR(-EFAULT);
 }
 
 /* Try to discard unwanted pages */
@@ -2218,7 +2225,9 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
 
        __i915_gem_object_reset_page_iter(obj);
 
-       obj->ops->put_pages(obj, pages);
+       if (!IS_ERR(pages))
+               obj->ops->put_pages(obj, pages);
+
 unlock:
        mutex_unlock(&obj->mm.lock);
 }
@@ -2437,7 +2446,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
        if (err)
                return err;
 
-       if (unlikely(!obj->mm.pages)) {
+       if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
                err = ____i915_gem_object_get_pages(obj);
                if (err)
                        goto unlock;
@@ -2515,7 +2524,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
 
        pinned = true;
        if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) {
-               if (unlikely(!obj->mm.pages)) {
+               if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
                        ret = ____i915_gem_object_get_pages(obj);
                        if (ret)
                                goto err_unlock;
@@ -2563,6 +2572,75 @@ err_unlock:
        goto out_unlock;
 }
 
+static int
+i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
+                          const struct drm_i915_gem_pwrite *arg)
+{
+       struct address_space *mapping = obj->base.filp->f_mapping;
+       char __user *user_data = u64_to_user_ptr(arg->data_ptr);
+       u64 remain, offset;
+       unsigned int pg;
+
+       /* Before we instantiate/pin the backing store for our use, we
+        * can prepopulate the shmemfs filp efficiently using a write into
+        * the pagecache. We avoid the penalty of instantiating all the
+        * pages, important if the user is just writing to a few and never
+        * uses the object on the GPU, and using a direct write into shmemfs
+        * allows it to avoid the cost of retrieving a page (either swapin
+        * or clearing-before-use) before it is overwritten.
+        */
+       if (READ_ONCE(obj->mm.pages))
+               return -ENODEV;
+
+       /* Before the pages are instantiated the object is treated as being
+        * in the CPU domain. The pages will be clflushed as required before
+        * use, and we can freely write into the pages directly. If userspace
+        * races pwrite with any other operation; corruption will ensue -
+        * that is userspace's prerogative!
+        */
+
+       remain = arg->size;
+       offset = arg->offset;
+       pg = offset_in_page(offset);
+
+       do {
+               unsigned int len, unwritten;
+               struct page *page;
+               void *data, *vaddr;
+               int err;
+
+               len = PAGE_SIZE - pg;
+               if (len > remain)
+                       len = remain;
+
+               err = pagecache_write_begin(obj->base.filp, mapping,
+                                           offset, len, 0,
+                                           &page, &data);
+               if (err < 0)
+                       return err;
+
+               vaddr = kmap(page);
+               unwritten = copy_from_user(vaddr + pg, user_data, len);
+               kunmap(page);
+
+               err = pagecache_write_end(obj->base.filp, mapping,
+                                         offset, len, len - unwritten,
+                                         page, data);
+               if (err < 0)
+                       return err;
+
+               if (unwritten)
+                       return -EFAULT;
+
+               remain -= len;
+               user_data += len;
+               offset += len;
+               pg = 0;
+       } while (remain);
+
+       return 0;
+}
+
 static bool ban_context(const struct i915_gem_context *ctx)
 {
        return (i915_gem_context_is_bannable(ctx) &&
@@ -2641,7 +2719,16 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
        for_each_engine(engine, dev_priv, id) {
                struct drm_i915_gem_request *request;
 
+               /* Prevent request submission to the hardware until we have
+                * completed the reset in i915_gem_reset_finish(). If a request
+                * is completed by one engine, it may then queue a request
+                * to a second via its engine->irq_tasklet *just* as we are
+                * calling engine->init_hw() and also writing the ELSP.
+                * Turning off the engine->irq_tasklet until the reset is over
+                * prevents the race.
+                */
                tasklet_kill(&engine->irq_tasklet);
+               tasklet_disable(&engine->irq_tasklet);
 
                if (engine_stalled(engine)) {
                        request = i915_gem_find_active_request(engine);
@@ -2756,7 +2843,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
        engine->reset_hw(engine, request);
 }
 
-void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
+void i915_gem_reset(struct drm_i915_private *dev_priv)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
@@ -2778,6 +2865,17 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
        }
 }
 
+void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+       for_each_engine(engine, dev_priv, id)
+               tasklet_enable(&engine->irq_tasklet);
+}
+
 static void nop_submit_request(struct drm_i915_gem_request *request)
 {
        dma_fence_set_error(&request->fence, -EIO);
@@ -3029,6 +3127,16 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
                args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));
                if (args->timeout_ns < 0)
                        args->timeout_ns = 0;
+
+               /*
+                * Apparently ktime isn't accurate enough and occasionally has a
+                * bit of mismatch in the jiffies<->nsecs<->ktime loop. So patch
+                * things up to make the test happy. We allow up to 1 jiffy.
+                *
+                * This is a regression from the timespec->ktime conversion.
+                */
+               if (ret == -ETIME && !nsecs_to_jiffies(args->timeout_ns))
+                       args->timeout_ns = 0;
        }
 
        i915_gem_object_put(obj);
@@ -3974,8 +4082,11 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 static const struct drm_i915_gem_object_ops i915_gem_object_ops = {
        .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
                 I915_GEM_OBJECT_IS_SHRINKABLE,
+
        .get_pages = i915_gem_object_get_pages_gtt,
        .put_pages = i915_gem_object_put_pages_gtt,
+
+       .pwrite = i915_gem_object_pwrite_gtt,
 };
 
 struct drm_i915_gem_object *
@@ -4583,8 +4694,6 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
        init_waitqueue_head(&dev_priv->gpu_error.wait_queue);
        init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
 
-       dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
-
        init_waitqueue_head(&dev_priv->pending_flip_queue);
 
        dev_priv->mm.interruptible = true;
index 17f90c6182081c932652715ed34724f1c71b373d..e2d83b6d376b03e8bdef54bc9ed9e7c9a3d0138c 100644 (file)
@@ -311,7 +311,6 @@ __create_hw_context(struct drm_i915_private *dev_priv,
        ctx->ring_size = 4 * PAGE_SIZE;
        ctx->desc_template = GEN8_CTX_ADDRESSING_MODE(dev_priv) <<
                             GEN8_CTX_ADDRESSING_MODE_SHIFT;
-       ATOMIC_INIT_NOTIFIER_HEAD(&ctx->status_notifier);
 
        /* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not
         * present or not in use we still need a small bias as ring wraparound
index 0ac750b90f3d33f5585351fe284da68eaf6cb1e2..e9c008fe14b1d77500e7d456ef37705053685130 100644 (file)
@@ -160,9 +160,6 @@ struct i915_gem_context {
        /** desc_template: invariant fields for the HW context descriptor */
        u32 desc_template;
 
-       /** status_notifier: list of callbacks for context-switch changes */
-       struct atomic_notifier_head status_notifier;
-
        /** guilty_count: How many times this context has caused a GPU hang. */
        unsigned int guilty_count;
        /**
index c181b1bb3d2c9e72addb040ee8a0d5a4b52f06c9..3be2503aa042c0c48cb2745ad26e9316a2409484 100644 (file)
@@ -293,12 +293,12 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
                 * those as well to make room for our guard pages.
                 */
                if (check_color) {
-                       if (vma->node.start + vma->node.size == node->start) {
-                               if (vma->node.color == node->color)
+                       if (node->start + node->size == target->start) {
+                               if (node->color == target->color)
                                        continue;
                        }
-                       if (vma->node.start == node->start + node->size) {
-                               if (vma->node.color == node->color)
+                       if (node->start == target->start + target->size) {
+                               if (node->color == target->color)
                                        continue;
                        }
                }
index d02cfaefe1c84e86cf39d74aa1ef09a4d1345af1..30e0675fd7dab7949d3cb3cb498be852d7448ac9 100644 (file)
@@ -1408,10 +1408,7 @@ execbuf_submit(struct i915_execbuffer_params *params,
               struct drm_i915_gem_execbuffer2 *args,
               struct list_head *vmas)
 {
-       struct drm_i915_private *dev_priv = params->request->i915;
        u64 exec_start, exec_len;
-       int instp_mode;
-       u32 instp_mask;
        int ret;
 
        ret = i915_gem_execbuffer_move_to_gpu(params->request, vmas);
@@ -1422,56 +1419,11 @@ execbuf_submit(struct i915_execbuffer_params *params,
        if (ret)
                return ret;
 
-       instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
-       instp_mask = I915_EXEC_CONSTANTS_MASK;
-       switch (instp_mode) {
-       case I915_EXEC_CONSTANTS_REL_GENERAL:
-       case I915_EXEC_CONSTANTS_ABSOLUTE:
-       case I915_EXEC_CONSTANTS_REL_SURFACE:
-               if (instp_mode != 0 && params->engine->id != RCS) {
-                       DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
-                       return -EINVAL;
-               }
-
-               if (instp_mode != dev_priv->relative_constants_mode) {
-                       if (INTEL_INFO(dev_priv)->gen < 4) {
-                               DRM_DEBUG("no rel constants on pre-gen4\n");
-                               return -EINVAL;
-                       }
-
-                       if (INTEL_INFO(dev_priv)->gen > 5 &&
-                           instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
-                               DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
-                               return -EINVAL;
-                       }
-
-                       /* The HW changed the meaning on this bit on gen6 */
-                       if (INTEL_INFO(dev_priv)->gen >= 6)
-                               instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
-               }
-               break;
-       default:
-               DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
+       if (args->flags & I915_EXEC_CONSTANTS_MASK) {
+               DRM_DEBUG("I915_EXEC_CONSTANTS_* unsupported\n");
                return -EINVAL;
        }
 
-       if (params->engine->id == RCS &&
-           instp_mode != dev_priv->relative_constants_mode) {
-               struct intel_ring *ring = params->request->ring;
-
-               ret = intel_ring_begin(params->request, 4);
-               if (ret)
-                       return ret;
-
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit_reg(ring, INSTPM);
-               intel_ring_emit(ring, instp_mask << 16 | instp_mode);
-               intel_ring_advance(ring);
-
-               dev_priv->relative_constants_mode = instp_mode;
-       }
-
        if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
                ret = i915_reset_gen7_sol_offsets(params->request);
                if (ret)
index bf90b07163d1266a6bb0c87f036e84fa78181991..76b80a0be79767be189c94694434c338c1f97e6a 100644 (file)
@@ -54,6 +54,9 @@ struct drm_i915_gem_object_ops {
        struct sg_table *(*get_pages)(struct drm_i915_gem_object *);
        void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);
 
+       int (*pwrite)(struct drm_i915_gem_object *,
+                     const struct drm_i915_gem_pwrite *);
+
        int (*dmabuf_export)(struct drm_i915_gem_object *);
        void (*release)(struct drm_i915_gem_object *);
 };
index 401006b4c6a36bf2a8058c2b47eb38105ab5baf4..d5d2b4c6ed382d687719a088d943580ccacbba15 100644 (file)
@@ -263,7 +263,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)
                                I915_SHRINK_BOUND |
                                I915_SHRINK_UNBOUND |
                                I915_SHRINK_ACTIVE);
-       rcu_barrier(); /* wait until our RCU delayed slab frees are completed */
+       synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */
 
        return freed;
 }
index e6ffef2f707a01934a3a6f777b1dc7548ef370c8..b6c886ac901bd78cfa7beb1a3aaaf706821a6d2b 100644 (file)
@@ -1046,68 +1046,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv,
        ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
 }
 
-static bool vlv_c0_above(struct drm_i915_private *dev_priv,
-                        const struct intel_rps_ei *old,
-                        const struct intel_rps_ei *now,
-                        int threshold)
-{
-       u64 time, c0;
-       unsigned int mul = 100;
-
-       if (old->cz_clock == 0)
-               return false;
-
-       if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
-               mul <<= 8;
-
-       time = now->cz_clock - old->cz_clock;
-       time *= threshold * dev_priv->czclk_freq;
-
-       /* Workload can be split between render + media, e.g. SwapBuffers
-        * being blitted in X after being rendered in mesa. To account for
-        * this we need to combine both engines into our activity counter.
-        */
-       c0 = now->render_c0 - old->render_c0;
-       c0 += now->media_c0 - old->media_c0;
-       c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
-
-       return c0 >= time;
-}
-
 void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)
 {
-       vlv_c0_read(dev_priv, &dev_priv->rps.down_ei);
-       dev_priv->rps.up_ei = dev_priv->rps.down_ei;
+       memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));
 }
 
 static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
 {
+       const struct intel_rps_ei *prev = &dev_priv->rps.ei;
        struct intel_rps_ei now;
        u32 events = 0;
 
-       if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0)
+       if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)
                return 0;
 
        vlv_c0_read(dev_priv, &now);
        if (now.cz_clock == 0)
                return 0;
 
-       if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) {
-               if (!vlv_c0_above(dev_priv,
-                                 &dev_priv->rps.down_ei, &now,
-                                 dev_priv->rps.down_threshold))
-                       events |= GEN6_PM_RP_DOWN_THRESHOLD;
-               dev_priv->rps.down_ei = now;
-       }
+       if (prev->cz_clock) {
+               u64 time, c0;
+               unsigned int mul;
+
+               mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
+               if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
+                       mul <<= 8;
 
-       if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
-               if (vlv_c0_above(dev_priv,
-                                &dev_priv->rps.up_ei, &now,
-                                dev_priv->rps.up_threshold))
-                       events |= GEN6_PM_RP_UP_THRESHOLD;
-               dev_priv->rps.up_ei = now;
+               time = now.cz_clock - prev->cz_clock;
+               time *= dev_priv->czclk_freq;
+
+               /* Workload can be split between render + media,
+                * e.g. SwapBuffers being blitted in X after being rendered in
+                * mesa. To account for this we need to combine both engines
+                * into our activity counter.
+                */
+               c0 = now.render_c0 - prev->render_c0;
+               c0 += now.media_c0 - prev->media_c0;
+               c0 *= mul;
+
+               if (c0 > time * dev_priv->rps.up_threshold)
+                       events = GEN6_PM_RP_UP_THRESHOLD;
+               else if (c0 < time * dev_priv->rps.down_threshold)
+                       events = GEN6_PM_RP_DOWN_THRESHOLD;
        }
 
+       dev_priv->rps.ei = now;
        return events;
 }
 
@@ -4228,7 +4211,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        /* Let's track the enabled rps events */
        if (IS_VALLEYVIEW(dev_priv))
                /* WaGsvRC0ResidencyMethod:vlv */
-               dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED;
+               dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
        else
                dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
@@ -4266,6 +4249,16 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        if (!IS_GEN2(dev_priv))
                dev->vblank_disable_immediate = true;
 
+       /* Most platforms treat the display irq block as an always-on
+        * power domain. vlv/chv can disable it at runtime and need
+        * special care to avoid writing any of the display block registers
+        * outside of the power domain. We defer setting up the display irqs
+        * in this case to the runtime pm.
+        */
+       dev_priv->display_irqs_enabled = true;
+       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+               dev_priv->display_irqs_enabled = false;
+
        dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
        dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
 
index 155906e848120ae2e1de533d81658080c546888d..df20e9bc1c0f3dee67eb555ae20741d907a6b430 100644 (file)
@@ -512,10 +512,36 @@ err_unpin:
        return ret;
 }
 
+static void
+i915_vma_remove(struct i915_vma *vma)
+{
+       struct drm_i915_gem_object *obj = vma->obj;
+
+       GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
+       GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
+
+       drm_mm_remove_node(&vma->node);
+       list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
+
+       /* Since the unbound list is global, only move to that list if
+        * no more VMAs exist.
+        */
+       if (--obj->bind_count == 0)
+               list_move_tail(&obj->global_link,
+                              &to_i915(obj->base.dev)->mm.unbound_list);
+
+       /* And finally now the object is completely decoupled from this vma,
+        * we can drop its hold on the backing storage and allow it to be
+        * reaped by the shrinker.
+        */
+       i915_gem_object_unpin_pages(obj);
+       GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count);
+}
+
 int __i915_vma_do_pin(struct i915_vma *vma,
                      u64 size, u64 alignment, u64 flags)
 {
-       unsigned int bound = vma->flags;
+       const unsigned int bound = vma->flags;
        int ret;
 
        lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
@@ -524,18 +550,18 @@ int __i915_vma_do_pin(struct i915_vma *vma,
 
        if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {
                ret = -EBUSY;
-               goto err;
+               goto err_unpin;
        }
 
        if ((bound & I915_VMA_BIND_MASK) == 0) {
                ret = i915_vma_insert(vma, size, alignment, flags);
                if (ret)
-                       goto err;
+                       goto err_unpin;
        }
 
        ret = i915_vma_bind(vma, vma->obj->cache_level, flags);
        if (ret)
-               goto err;
+               goto err_remove;
 
        if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND)
                __i915_vma_set_map_and_fenceable(vma);
@@ -544,7 +570,12 @@ int __i915_vma_do_pin(struct i915_vma *vma,
        GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
        return 0;
 
-err:
+err_remove:
+       if ((bound & I915_VMA_BIND_MASK) == 0) {
+               GEM_BUG_ON(vma->pages);
+               i915_vma_remove(vma);
+       }
+err_unpin:
        __i915_vma_unpin(vma);
        return ret;
 }
@@ -657,9 +688,6 @@ int i915_vma_unbind(struct i915_vma *vma)
        }
        vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
 
-       drm_mm_remove_node(&vma->node);
-       list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
-
        if (vma->pages != obj->mm.pages) {
                GEM_BUG_ON(!vma->pages);
                sg_free_table(vma->pages);
@@ -667,18 +695,7 @@ int i915_vma_unbind(struct i915_vma *vma)
        }
        vma->pages = NULL;
 
-       /* Since the unbound list is global, only move to that list if
-        * no more VMAs exist. */
-       if (--obj->bind_count == 0)
-               list_move_tail(&obj->global_link,
-                              &to_i915(obj->base.dev)->mm.unbound_list);
-
-       /* And finally now the object is completely decoupled from this vma,
-        * we can drop its hold on the backing storage and allow it to be
-        * reaped by the shrinker.
-        */
-       i915_gem_object_unpin_pages(obj);
-       GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count);
+       i915_vma_remove(vma);
 
 destroy:
        if (unlikely(i915_vma_is_closed(vma)))
index 0085bc745f6aa5256cf21c1ae76dd2cbce80e387..de219b71fb76ecbfab51d58bd379064b555c8241 100644 (file)
@@ -35,7 +35,6 @@
  */
 
 #define I915_CSR_GLK "i915/glk_dmc_ver1_01.bin"
-MODULE_FIRMWARE(I915_CSR_GLK);
 #define GLK_CSR_VERSION_REQUIRED       CSR_VERSION(1, 1)
 
 #define I915_CSR_KBL "i915/kbl_dmc_ver1_01.bin"
index 01341670738fbb118d8402bbda62d7234c8c3863..ed1f4f272b4fb3907adeea175216173fea5253fb 100644 (file)
@@ -3669,10 +3669,6 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,
        /* drm_atomic_helper_update_legacy_modeset_state might not be called. */
        crtc->base.mode = crtc->base.state->mode;
 
-       DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n",
-                     old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h,
-                     pipe_config->pipe_src_w, pipe_config->pipe_src_h);
-
        /*
         * Update pipe size and adjust fitter if needed: the reason for this is
         * that in compute_mode_changes we check the native mode (not the pfit
@@ -4796,23 +4792,17 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)
        struct intel_crtc_scaler_state *scaler_state =
                &crtc->config->scaler_state;
 
-       DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
-
        if (crtc->config->pch_pfit.enabled) {
                int id;
 
-               if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
-                       DRM_ERROR("Requesting pfit without getting a scaler first\n");
+               if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
                        return;
-               }
 
                id = scaler_state->scaler_id;
                I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
                        PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
                I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
                I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
-
-               DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);
        }
 }
 
@@ -14379,6 +14369,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
        } while (progress);
 }
 
+static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
+{
+       struct intel_atomic_state *state, *next;
+       struct llist_node *freed;
+
+       freed = llist_del_all(&dev_priv->atomic_helper.free_list);
+       llist_for_each_entry_safe(state, next, freed, freed)
+               drm_atomic_state_put(&state->base);
+}
+
+static void intel_atomic_helper_free_state_worker(struct work_struct *work)
+{
+       struct drm_i915_private *dev_priv =
+               container_of(work, typeof(*dev_priv), atomic_helper.free_work);
+
+       intel_atomic_helper_free_state(dev_priv);
+}
+
 static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
@@ -14545,6 +14553,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
         * can happen also when the device is completely off.
         */
        intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
+
+       intel_atomic_helper_free_state(dev_priv);
 }
 
 static void intel_atomic_commit_work(struct work_struct *work)
@@ -14946,17 +14956,19 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
                to_intel_atomic_state(old_crtc_state->state);
        bool modeset = needs_modeset(crtc->state);
 
+       if (!modeset &&
+           (intel_cstate->base.color_mgmt_changed ||
+            intel_cstate->update_pipe)) {
+               intel_color_set_csc(crtc->state);
+               intel_color_load_luts(crtc->state);
+       }
+
        /* Perform vblank evasion around commit operation */
        intel_pipe_update_start(intel_crtc);
 
        if (modeset)
                goto out;
 
-       if (crtc->state->color_mgmt_changed || to_intel_crtc_state(crtc->state)->update_pipe) {
-               intel_color_set_csc(crtc->state);
-               intel_color_load_luts(crtc->state);
-       }
-
        if (intel_cstate->update_pipe)
                intel_update_pipe_config(intel_crtc, old_intel_cstate);
        else if (INTEL_GEN(dev_priv) >= 9)
@@ -16599,18 +16611,6 @@ fail:
        drm_modeset_acquire_fini(&ctx);
 }
 
-static void intel_atomic_helper_free_state(struct work_struct *work)
-{
-       struct drm_i915_private *dev_priv =
-               container_of(work, typeof(*dev_priv), atomic_helper.free_work);
-       struct intel_atomic_state *state, *next;
-       struct llist_node *freed;
-
-       freed = llist_del_all(&dev_priv->atomic_helper.free_list);
-       llist_for_each_entry_safe(state, next, freed, freed)
-               drm_atomic_state_put(&state->base);
-}
-
 int intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -16631,7 +16631,7 @@ int intel_modeset_init(struct drm_device *dev)
        dev->mode_config.funcs = &intel_mode_funcs;
 
        INIT_WORK(&dev_priv->atomic_helper.free_work,
-                 intel_atomic_helper_free_state);
+                 intel_atomic_helper_free_state_worker);
 
        intel_init_quirks(dev);
 
@@ -16696,12 +16696,11 @@ int intel_modeset_init(struct drm_device *dev)
                }
        }
 
-       intel_update_czclk(dev_priv);
-       intel_update_cdclk(dev_priv);
-       dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
-
        intel_shared_dpll_init(dev);
 
+       intel_update_czclk(dev_priv);
+       intel_modeset_init_hw(dev);
+
        if (dev_priv->max_cdclk_freq == 0)
                intel_update_max_cdclk(dev_priv);
 
@@ -17258,8 +17257,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
        intel_init_gt_powersave(dev_priv);
 
-       intel_modeset_init_hw(dev);
-
        intel_setup_overlay(dev_priv);
 }
 
index 371acf109e343295ae060c4cf49908bf5607118e..ab1be5c80ea5960df983940e70f98f0d49cbd8e1 100644 (file)
@@ -105,6 +105,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
        /* Nothing to do here, execute in order of dependencies */
        engine->schedule = NULL;
 
+       ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
+
        dev_priv->engine[id] = engine;
        return 0;
 }
index 1b8ba2e77539577f5eb997f9e1eb315f1f7ae078..2d449fb5d1d2b02dc016ebb50a026733b50acbf3 100644 (file)
@@ -357,14 +357,13 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
                                    bool *enabled, int width, int height)
 {
        struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
-       unsigned long conn_configured, mask;
+       unsigned long conn_configured, conn_seq, mask;
        unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
        int i, j;
        bool *save_enabled;
        bool fallback = true;
        int num_connectors_enabled = 0;
        int num_connectors_detected = 0;
-       int pass = 0;
 
        save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
        if (!save_enabled)
@@ -374,6 +373,7 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
        mask = BIT(count) - 1;
        conn_configured = 0;
 retry:
+       conn_seq = conn_configured;
        for (i = 0; i < count; i++) {
                struct drm_fb_helper_connector *fb_conn;
                struct drm_connector *connector;
@@ -387,7 +387,7 @@ retry:
                if (conn_configured & BIT(i))
                        continue;
 
-               if (pass == 0 && !connector->has_tile)
+               if (conn_seq == 0 && !connector->has_tile)
                        continue;
 
                if (connector->status == connector_status_connected)
@@ -498,10 +498,8 @@ retry:
                conn_configured |= BIT(i);
        }
 
-       if ((conn_configured & mask) != mask) {
-               pass++;
+       if ((conn_configured & mask) != mask && conn_configured != conn_seq)
                goto retry;
-       }
 
        /*
         * If the BIOS didn't enable everything it could, fall back to have the
index d23c0fcff7516a9f3df4363010e2c3dfa84e3c00..8c04eca84351cbbe5d7f385fd6d262f40a080a28 100644 (file)
@@ -77,6 +77,11 @@ int intel_gvt_init(struct drm_i915_private *dev_priv)
                goto bail;
        }
 
+       if (!i915.enable_execlists) {
+               DRM_INFO("GPU guest virtualisation [GVT-g] disabled due to disabled execlist submission [i915.enable_execlists module parameter]\n");
+               goto bail;
+       }
+
        /*
         * We're not in host or fail to find a MPT module, disable GVT-g
         */
index ebae2bd839189c07588e88a526f3f804d08157b3..24b2fa5b62824dfa86d87c9e5d1c630957192867 100644 (file)
@@ -1298,16 +1298,34 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
 
 static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc_state->base.crtc->dev;
+       struct drm_i915_private *dev_priv =
+               to_i915(crtc_state->base.crtc->dev);
+       struct drm_atomic_state *state = crtc_state->base.state;
+       struct drm_connector_state *connector_state;
+       struct drm_connector *connector;
+       int i;
 
-       if (HAS_GMCH_DISPLAY(to_i915(dev)))
+       if (HAS_GMCH_DISPLAY(dev_priv))
                return false;
 
        /*
         * HDMI 12bpc affects the clocks, so it's only possible
         * when not cloning with other encoder types.
         */
-       return crtc_state->output_types == 1 << INTEL_OUTPUT_HDMI;
+       if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI)
+               return false;
+
+       for_each_connector_in_state(state, connector, connector_state, i) {
+               const struct drm_display_info *info = &connector->display_info;
+
+               if (connector_state->crtc != crtc_state->base.crtc)
+                       continue;
+
+               if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
+                       return false;
+       }
+
+       return true;
 }
 
 bool intel_hdmi_compute_config(struct intel_encoder *encoder,
index b62e3f8ad415f6173470c90a3cb1b35b04f91c4b..54208bef7a83561eb72c29d26079fa447211203c 100644 (file)
@@ -219,7 +219,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
                        }
                }
        }
-       if (dev_priv->display.hpd_irq_setup)
+       if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup)
                dev_priv->display.hpd_irq_setup(dev_priv);
        spin_unlock_irq(&dev_priv->irq_lock);
 
@@ -425,7 +425,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
                }
        }
 
-       if (storm_detected)
+       if (storm_detected && dev_priv->display_irqs_enabled)
                dev_priv->display.hpd_irq_setup(dev_priv);
        spin_unlock(&dev_priv->irq_lock);
 
@@ -471,10 +471,12 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)
         * Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked checks happy.
         */
-       spin_lock_irq(&dev_priv->irq_lock);
-       if (dev_priv->display.hpd_irq_setup)
-               dev_priv->display.hpd_irq_setup(dev_priv);
-       spin_unlock_irq(&dev_priv->irq_lock);
+       if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup) {
+               spin_lock_irq(&dev_priv->irq_lock);
+               if (dev_priv->display_irqs_enabled)
+                       dev_priv->display.hpd_irq_setup(dev_priv);
+               spin_unlock_irq(&dev_priv->irq_lock);
+       }
 }
 
 static void i915_hpd_poll_init_work(struct work_struct *work)
index ebf8023d21e6fba52c01b54d46fb3456b4709731..471af3b480adc38a3a48c27d1999805836cf5630 100644 (file)
@@ -345,7 +345,8 @@ execlists_context_status_change(struct drm_i915_gem_request *rq,
        if (!IS_ENABLED(CONFIG_DRM_I915_GVT))
                return;
 
-       atomic_notifier_call_chain(&rq->ctx->status_notifier, status, rq);
+       atomic_notifier_call_chain(&rq->engine->context_status_notifier,
+                                  status, rq);
 }
 
 static void
index 249623d45be0caa3e891e8a272706dff84dbc4be..6a29784d2b4137c9805e85ffb80265e05e46af53 100644 (file)
@@ -4891,6 +4891,12 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
                break;
        }
 
+       /* When byt can survive without system hang with dynamic
+        * sw freq adjustments, this restriction can be lifted.
+        */
+       if (IS_VALLEYVIEW(dev_priv))
+               goto skip_hw_write;
+
        I915_WRITE(GEN6_RP_UP_EI,
                   GT_INTERVAL_FROM_US(dev_priv, ei_up));
        I915_WRITE(GEN6_RP_UP_THRESHOLD,
@@ -4911,6 +4917,7 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
                   GEN6_RP_UP_BUSY_AVG |
                   GEN6_RP_DOWN_IDLE_AVG);
 
+skip_hw_write:
        dev_priv->rps.power = new_power;
        dev_priv->rps.up_threshold = threshold_up;
        dev_priv->rps.down_threshold = threshold_down;
@@ -4921,8 +4928,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
 {
        u32 mask = 0;
 
+       /* We use UP_EI_EXPIRED interupts for both up/down in manual mode */
        if (val > dev_priv->rps.min_freq_softlimit)
-               mask |= GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
+               mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
        if (val < dev_priv->rps.max_freq_softlimit)
                mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
 
@@ -5032,7 +5040,7 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv)
 {
        mutex_lock(&dev_priv->rps.hw_lock);
        if (dev_priv->rps.enabled) {
-               if (dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED))
+               if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)
                        gen6_rps_reset_ei(dev_priv);
                I915_WRITE(GEN6_PMINTRMSK,
                           gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
@@ -7916,10 +7924,10 @@ static bool skl_pcode_try_request(struct drm_i915_private *dev_priv, u32 mbox,
  * @timeout_base_ms: timeout for polling with preemption enabled
  *
  * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE
- * reports an error or an overall timeout of @timeout_base_ms+10 ms expires.
+ * reports an error or an overall timeout of @timeout_base_ms+50 ms expires.
  * The request is acknowledged once the PCODE reply dword equals @reply after
  * applying @reply_mask. Polling is first attempted with preemption enabled
- * for @timeout_base_ms and if this times out for another 10 ms with
+ * for @timeout_base_ms and if this times out for another 50 ms with
  * preemption disabled.
  *
  * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some
@@ -7955,14 +7963,15 @@ int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
         * worst case) _and_ PCODE was busy for some reason even after a
         * (queued) request and @timeout_base_ms delay. As a workaround retry
         * the poll with preemption disabled to maximize the number of
-        * requests. Increase the timeout from @timeout_base_ms to 10ms to
+        * requests. Increase the timeout from @timeout_base_ms to 50ms to
         * account for interrupts that could reduce the number of these
-        * requests.
+        * requests, and for any quirks of the PCODE firmware that delays
+        * the request completion.
         */
        DRM_DEBUG_KMS("PCODE timeout, retrying with preemption disabled\n");
        WARN_ON_ONCE(timeout_base_ms > 3);
        preempt_disable();
-       ret = wait_for_atomic(COND, 10);
+       ret = wait_for_atomic(COND, 50);
        preempt_enable();
 
 out:
index 79c2b8d72322cf58cacd3f732c5a55ce0ef68f3b..13dccb18cd43ed85aee58a6a15618c515094a83b 100644 (file)
@@ -403,6 +403,9 @@ struct intel_engine_cs {
         */
        struct i915_gem_context *legacy_active_context;
 
+       /* status_notifier: list of callbacks for context-switch changes */
+       struct atomic_notifier_head context_status_notifier;
+
        struct intel_engine_hangcheck hangcheck;
 
        bool needs_cmd_parser;
index 9ef54688872a86a70ab020a64b7209e040de70e0..9481ca9a3ae7e0a342957baf655a34f570a51eae 100644 (file)
@@ -254,9 +254,6 @@ skl_update_plane(struct drm_plane *drm_plane,
                int scaler_id = plane_state->scaler_id;
                const struct intel_scaler *scaler;
 
-               DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n",
-                             plane_id, PS_PLANE_SEL(plane_id));
-
                scaler = &crtc_state->scaler_state.scalers[scaler_id];
 
                I915_WRITE(SKL_PS_CTRL(pipe, scaler_id),
index abe08885a5ba4ef1726d67809544534cf35a57df..b7ff592b14f5e00d68ff1cf6440dd45d6959606d 100644 (file)
@@ -119,6 +119,8 @@ fw_domains_get(struct drm_i915_private *dev_priv, enum forcewake_domains fw_doma
 
        for_each_fw_domain_masked(d, fw_domains, dev_priv)
                fw_domain_wait_ack(d);
+
+       dev_priv->uncore.fw_domains_active |= fw_domains;
 }
 
 static void
@@ -130,6 +132,8 @@ fw_domains_put(struct drm_i915_private *dev_priv, enum forcewake_domains fw_doma
                fw_domain_put(d);
                fw_domain_posting_read(d);
        }
+
+       dev_priv->uncore.fw_domains_active &= ~fw_domains;
 }
 
 static void
@@ -240,10 +244,8 @@ intel_uncore_fw_release_timer(struct hrtimer *timer)
        if (WARN_ON(domain->wake_count == 0))
                domain->wake_count++;
 
-       if (--domain->wake_count == 0) {
+       if (--domain->wake_count == 0)
                dev_priv->uncore.funcs.force_wake_put(dev_priv, domain->mask);
-               dev_priv->uncore.fw_domains_active &= ~domain->mask;
-       }
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
@@ -454,10 +456,8 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
                        fw_domains &= ~domain->mask;
        }
 
-       if (fw_domains) {
+       if (fw_domains)
                dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
-               dev_priv->uncore.fw_domains_active |= fw_domains;
-       }
 }
 
 /**
@@ -968,7 +968,6 @@ static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv,
                fw_domain_arm_timer(domain);
 
        dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
-       dev_priv->uncore.fw_domains_active |= fw_domains;
 }
 
 static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
index af267c35d813cc7548f060ef5771d6cd4232b4c9..ee5883f59be5a1992c6bdd20c751285079f5d3c1 100644 (file)
@@ -147,9 +147,6 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
        struct drm_gem_object *obj = buffer->priv;
        int ret = 0;
 
-       if (WARN_ON(!obj->filp))
-               return -EINVAL;
-
        ret = drm_gem_mmap_obj(obj, omap_gem_mmap_size(obj), vma);
        if (ret < 0)
                return ret;
index d12b8978142f69b52e19a159f9a628080f7a18e5..c7af9fdd20c729184654222dfc8b4bc6a870c066 100644 (file)
@@ -2984,6 +2984,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                    (rdev->pdev->device == 0x6667)) {
                        max_sclk = 75000;
                }
+       } else if (rdev->family == CHIP_OLAND) {
+               if ((rdev->pdev->revision == 0xC7) ||
+                   (rdev->pdev->revision == 0x80) ||
+                   (rdev->pdev->revision == 0x81) ||
+                   (rdev->pdev->revision == 0x83) ||
+                   (rdev->pdev->revision == 0x87) ||
+                   (rdev->pdev->device == 0x6604) ||
+                   (rdev->pdev->device == 0x6605)) {
+                       max_sclk = 75000;
+               }
        }
 
        if (rps->vce_active) {
index f80bf9385e412db766424bf00cacd76458a64a8e..d745e8b50fb86458d09e400f5c35c9d257f4de2b 100644 (file)
@@ -464,6 +464,7 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+       unsigned long flags;
 
        WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
        mutex_lock(&tilcdc_crtc->enable_lock);
@@ -484,7 +485,17 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)
        tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,
                          LCDC_PALETTE_LOAD_MODE(DATA_ONLY),
                          LCDC_PALETTE_LOAD_MODE_MASK);
+
+       /* There is no real chance for a race here as the time stamp
+        * is taken before the raster DMA is started. The spin-lock is
+        * taken to have a memory barrier after taking the time-stamp
+        * and to avoid a context switch between taking the stamp and
+        * enabling the raster.
+        */
+       spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
+       tilcdc_crtc->last_vblank = ktime_get();
        tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+       spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
 
        drm_crtc_vblank_on(crtc);
 
@@ -539,7 +550,6 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown)
        }
 
        drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
-       tilcdc_crtc->last_vblank = 0;
 
        tilcdc_crtc->enabled = false;
        mutex_unlock(&tilcdc_crtc->enable_lock);
@@ -602,7 +612,6 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
 {
        struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
        struct drm_device *dev = crtc->dev;
-       unsigned long flags;
 
        WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
 
@@ -614,28 +623,30 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
        drm_framebuffer_reference(fb);
 
        crtc->primary->fb = fb;
+       tilcdc_crtc->event = event;
 
-       spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
+       mutex_lock(&tilcdc_crtc->enable_lock);
 
-       if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
+       if (tilcdc_crtc->enabled) {
+               unsigned long flags;
                ktime_t next_vblank;
                s64 tdiff;
 
-               next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
-                       1000000 / crtc->hwmode.vrefresh);
+               spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
 
+               next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
+                                          1000000 / crtc->hwmode.vrefresh);
                tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
 
                if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)
                        tilcdc_crtc->next_fb = fb;
-       }
-
-       if (tilcdc_crtc->next_fb != fb)
-               set_scanout(crtc, fb);
+               else
+                       set_scanout(crtc, fb);
 
-       tilcdc_crtc->event = event;
+               spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
+       }
 
-       spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
+       mutex_unlock(&tilcdc_crtc->enable_lock);
 
        return 0;
 }
@@ -1036,5 +1047,5 @@ int tilcdc_crtc_create(struct drm_device *dev)
 
 fail:
        tilcdc_crtc_destroy(crtc);
-       return -ENOMEM;
+       return ret;
 }
index 1aeb80e5242461830f1d4075f0fb59bcb6ddc898..8c54cb8f5d6d1013ec1f4a39e8f88fcfe3333758 100644 (file)
@@ -175,11 +175,11 @@ config HID_CHERRY
        Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
-       tristate "Chicony Tactical pad"
+       tristate "Chicony devices"
        depends on HID
        default !EXPERT
        ---help---
-       Support for Chicony Tactical pad.
+       Support for Chicony Tactical pad and special keys on Chicony keyboards.
 
 config HID_CORSAIR
        tristate "Corsair devices"
@@ -190,6 +190,7 @@ config HID_CORSAIR
 
        Supported devices:
        - Vengeance K90
+       - Scimitar PRO RGB
 
 config HID_PRODIKEYS
        tristate "Prodikeys PC-MIDI Keyboard support"
index bc3cec199feefdf437d0c0141c5ff6f73aa10308..f04ed9aabc3f9fea0baf5b074acd83b6d07527c6 100644 (file)
@@ -86,6 +86,7 @@ static const struct hid_device_id ch_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ch_devices);
index e9e87d337446918f672771551f41041755d83d22..3ceb4a2af381f03d7f51b40cfe4d262be774de48 100644 (file)
@@ -1870,6 +1870,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
@@ -1910,6 +1911,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
index c0303f61c26a94f1998f6883d42a0fc8cb41f432..9ba5d98a118042a52dc40b895c3b2e8df67c0b39 100644 (file)
@@ -3,8 +3,10 @@
  *
  * Supported devices:
  *  - Vengeance K90 Keyboard
+ *  - Scimitar PRO RGB Gaming Mouse
  *
  * Copyright (c) 2015 Clement Vuchener
+ * Copyright (c) 2017 Oscar Campos
  */
 
 /*
@@ -670,10 +672,51 @@ static int corsair_input_mapping(struct hid_device *dev,
        return 0;
 }
 
+/*
+ * The report descriptor of Corsair Scimitar RGB Pro gaming mouse is
+ * non parseable as they define two consecutive Logical Minimum for
+ * the Usage Page (Consumer) in rdescs bytes 75 and 77 being 77 0x16
+ * that should be obviousy 0x26 for Logical Magimum of 16 bits. This
+ * prevents poper parsing of the report descriptor due Logical
+ * Minimum being larger than Logical Maximum.
+ *
+ * This driver fixes the report descriptor for:
+ * - USB ID b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse
+ */
+
+static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+        unsigned int *rsize)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+       if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
+               /*
+                * Corsair Scimitar RGB Pro report descriptor is broken and
+                * defines two different Logical Minimum for the Consumer
+                * Application. The byte 77 should be a 0x26 defining a 16
+                * bits integer for the Logical Maximum but it is a 0x16
+                * instead (Logical Minimum)
+                */
+               switch (hdev->product) {
+               case USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB:
+                       if (*rsize >= 172 && rdesc[75] == 0x15 && rdesc[77] == 0x16
+                       && rdesc[78] == 0xff && rdesc[79] == 0x0f) {
+                               hid_info(hdev, "Fixing up report descriptor\n");
+                               rdesc[77] = 0x26;
+                       }
+                       break;
+               }
+
+       }
+       return rdesc;
+}
+
 static const struct hid_device_id corsair_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
                .driver_data = CORSAIR_USE_K90_MACRO |
                               CORSAIR_USE_K90_BACKLIGHT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
+            USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
        {}
 };
 
@@ -686,10 +729,14 @@ static struct hid_driver corsair_driver = {
        .event = corsair_event,
        .remove = corsair_remove,
        .input_mapping = corsair_input_mapping,
+       .report_fixup = corsair_mouse_report_fixup,
 };
 
 module_hid_driver(corsair_driver);
 
 MODULE_LICENSE("GPL");
+/* Original K90 driver author */
 MODULE_AUTHOR("Clement Vuchener");
+/* Scimitar PRO RGB driver author */
+MODULE_AUTHOR("Oscar Campos");
 MODULE_DESCRIPTION("HID driver for Corsair devices");
index 86c95d30ac801f2895caef97a575955289d352a4..0e2e7c571d2261a148baec5bcddeb5cc7aa75e56 100644 (file)
 #define USB_DEVICE_ID_CORSAIR_K70RGB    0x1b13
 #define USB_DEVICE_ID_CORSAIR_STRAFE    0x1b15
 #define USB_DEVICE_ID_CORSAIR_K65RGB    0x1b17
+#define USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE  0x1b38
+#define USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE  0x1b39
+#define USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB  0x1b3e
 
 #define USB_VENDOR_ID_CREATIVELABS     0x041e
 #define USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51     0x322c
 
 #define USB_VENDOR_ID_JESS             0x0c45
 #define USB_DEVICE_ID_JESS_YUREX       0x1010
+#define USB_DEVICE_ID_JESS_ZEN_AIO_KBD 0x5112
 
 #define USB_VENDOR_ID_JESS2            0x0f30
 #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
index f405b07d03816506215bd19fe3c878393370484a..740996f9bdd49dde3d26659f68d2addbff291c60 100644 (file)
@@ -2632,6 +2632,8 @@ err_stop:
                sony_leds_remove(sc);
        if (sc->quirks & SONY_BATTERY_SUPPORT)
                sony_battery_remove(sc);
+       if (sc->touchpad)
+               sony_unregister_touchpad(sc);
        sony_cancel_work_sync(sc);
        kfree(sc->output_report_dmabuf);
        sony_remove_dev_list(sc);
index d6847a664446529831395a962aacab7cb49ab8f5..a69a3c88ab29f5fd736ad18a358fc185f63be99c 100644 (file)
@@ -80,6 +80,9 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
        { 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 },
index be8f7e2a026f428f51200e395792dd715a612eeb..994bddc55b82272c52d6c3224828f75a42d24dbe 100644 (file)
@@ -2579,7 +2579,9 @@ static void wacom_remove(struct hid_device *hdev)
 
        /* make sure we don't trigger the LEDs */
        wacom_led_groups_release(wacom);
-       wacom_release_resources(wacom);
+
+       if (wacom->wacom_wac.features.type != REMOTE)
+               wacom_release_resources(wacom);
 
        hid_set_drvdata(hdev, NULL);
 }
index 4aa3de9f1163b30eb64b4304f285a4167aef0cf0..94250c293be2a18b247e2be006a0e7e4faf4f6f8 100644 (file)
@@ -1959,8 +1959,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
                input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
                input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
                input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
-               input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
-               input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
+               if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) {
+                       input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
+                       input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
+               }
                break;
        case WACOM_HID_WD_FINGERWHEEL:
                wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
@@ -4197,10 +4199,10 @@ static const struct wacom_features wacom_features_0x343 =
          WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x360 =
        { "Wacom Intuos Pro M", 44800, 29600, 8191, 63,
-         INTUOSP2_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 9, .touch_max = 10 };
+         INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x361 =
        { "Wacom Intuos Pro L", 62200, 43200, 8191, 63,
-         INTUOSP2_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 9, .touch_max = 10 };
+         INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
        { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
index cccef87963e050afb99181d63d3ed5dcf401d5a1..975c43d446f8593d0e701efeaf8da133717cff74 100644 (file)
@@ -646,6 +646,9 @@ static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
                else
                        err = atk_read_value_new(sensor, value);
 
+               if (err)
+                       return err;
+
                sensor->is_valid = true;
                sensor->last_updated = jiffies;
                sensor->cached_value = *value;
index efb01c247e2d90680f02980af76148799f3823fc..4dfc7238313ebd393e0e4dc0e17bb4414d1e8b68 100644 (file)
@@ -3198,7 +3198,7 @@ static int __init sm_it87_init(void)
 {
        int sioaddr[2] = { REG_2E, REG_4E };
        struct it87_sio_data sio_data;
-       unsigned short isa_address;
+       unsigned short isa_address[2];
        bool found = false;
        int i, err;
 
@@ -3208,15 +3208,29 @@ static int __init sm_it87_init(void)
 
        for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
                memset(&sio_data, 0, sizeof(struct it87_sio_data));
-               isa_address = 0;
-               err = it87_find(sioaddr[i], &isa_address, &sio_data);
-               if (err || isa_address == 0)
+               isa_address[i] = 0;
+               err = it87_find(sioaddr[i], &isa_address[i], &sio_data);
+               if (err || isa_address[i] == 0)
                        continue;
+               /*
+                * Don't register second chip if its ISA address matches
+                * the first chip's ISA address.
+                */
+               if (i && isa_address[i] == isa_address[0])
+                       break;
 
-               err = it87_device_add(i, isa_address, &sio_data);
+               err = it87_device_add(i, isa_address[i], &sio_data);
                if (err)
                        goto exit_dev_unregister;
+
                found = true;
+
+               /*
+                * IT8705F may respond on both SIO addresses.
+                * Stop probing after finding one.
+                */
+               if (sio_data.type == it87)
+                       break;
        }
 
        if (!found) {
index c1b9275978f9d9ee9172e99e569de7dca48b491d..281491cca5103ad4b82e2f2a52be6f2408262bdb 100644 (file)
@@ -311,7 +311,7 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel,
                data->pwm[channel] = val << 8;
                err = i2c_smbus_write_word_swapped(client,
                                                   MAX31790_REG_PWMOUT(channel),
-                                                  val);
+                                                  data->pwm[channel]);
                break;
        case hwmon_pwm_enable:
                fan_config = data->fan_config[channel];
index ad9dec30bb304ffbbb0f67f01b753f7bc88cd891..4282ceca3d8f9f417a1a511b3d608896a7ad4159 100644 (file)
@@ -169,7 +169,9 @@ static irqreturn_t tiadc_irq_h(int irq, void *private)
 {
        struct iio_dev *indio_dev = private;
        struct tiadc_device *adc_dev = iio_priv(indio_dev);
-       unsigned int status, config;
+       unsigned int status, config, adc_fsm;
+       unsigned short count = 0;
+
        status = tiadc_readl(adc_dev, REG_IRQSTATUS);
 
        /*
@@ -183,6 +185,15 @@ static irqreturn_t tiadc_irq_h(int irq, void *private)
                tiadc_writel(adc_dev, REG_CTRL, config);
                tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
                                | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+
+               /* wait for idle state.
+                * ADC needs to finish the current conversion
+                * before disabling the module
+                */
+               do {
+                       adc_fsm = tiadc_readl(adc_dev, REG_ADCFSM);
+               } while (adc_fsm != 0x10 && count++ < 100);
+
                tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
                return IRQ_HANDLED;
        } else if (status & IRQENB_FIFO1THRES) {
index a3cce3a38300796b6b0899aa7fe2190481c7137d..ecf592d69043ae82e2e85184096471bfebef95e2 100644 (file)
@@ -51,8 +51,6 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
                        st->report_state.report_id,
                        st->report_state.index,
                        HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM);
-
-               poll_value = hid_sensor_read_poll_value(st);
        } else {
                int val;
 
@@ -89,7 +87,9 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
        sensor_hub_get_feature(st->hsdev, st->power_state.report_id,
                               st->power_state.index,
                               sizeof(state_val), &state_val);
-       if (state && poll_value)
+       if (state)
+               poll_value = hid_sensor_read_poll_value(st);
+       if (poll_value > 0)
                msleep_interruptible(poll_value * 2);
 
        return 0;
index 78532ce074497985dfa22fb881b3639e480ae7ed..81b572d7699a89bb17baa21321744c7b518e5c0a 100644 (file)
@@ -193,8 +193,8 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
        if (err < 0)
                goto out;
 
-       fifo_watermark = ((data & ~ST_LSM6DSX_FIFO_TH_MASK) << 8) |
-                         (fifo_watermark & ST_LSM6DSX_FIFO_TH_MASK);
+       fifo_watermark = ((data << 8) & ~ST_LSM6DSX_FIFO_TH_MASK) |
+                        (fifo_watermark & ST_LSM6DSX_FIFO_TH_MASK);
 
        wdata = cpu_to_le16(fifo_watermark);
        err = hw->tf->write(hw->dev, ST_LSM6DSX_REG_FIFO_THL_ADDR,
index 6dd8cbd7ce9531a5883173f34eb30edc45301083..e13370dc9b1cb424c4c2d43f0e92b9fadca78df9 100644 (file)
@@ -763,7 +763,7 @@ power_off:
        return ret;
 }
 
-static int __exit ak8974_remove(struct i2c_client *i2c)
+static int ak8974_remove(struct i2c_client *i2c)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
        struct ak8974 *ak8974 = iio_priv(indio_dev);
@@ -845,7 +845,7 @@ static struct i2c_driver ak8974_driver = {
                .of_match_table = of_match_ptr(ak8974_of_match),
        },
        .probe    = ak8974_probe,
-       .remove   = __exit_p(ak8974_remove),
+       .remove   = ak8974_remove,
        .id_table = ak8974_id,
 };
 module_i2c_driver(ak8974_driver);
index e95510117a6dd7069f1251796eaebd1ea8283693..f2ae75fa3128b9101985bb92e882b596404c7ebc 100644 (file)
@@ -29,7 +29,13 @@ static int __ib_process_cq(struct ib_cq *cq, int budget)
 {
        int i, n, completed = 0;
 
-       while ((n = ib_poll_cq(cq, IB_POLL_BATCH, cq->wc)) > 0) {
+       /*
+        * budget might be (-1) if the caller does not
+        * want to bound this call, thus we need unsigned
+        * minimum here.
+        */
+       while ((n = ib_poll_cq(cq, min_t(u32, IB_POLL_BATCH,
+                       budget - completed), cq->wc)) > 0) {
                for (i = 0; i < n; i++) {
                        struct ib_wc *wc = &cq->wc[i];
 
@@ -196,7 +202,7 @@ void ib_free_cq(struct ib_cq *cq)
                irq_poll_disable(&cq->iop);
                break;
        case IB_POLL_WORKQUEUE:
-               flush_work(&cq->work);
+               cancel_work_sync(&cq->work);
                break;
        default:
                WARN_ON_ONCE(1);
index 593d2ce6ec7cec115b58006a5cb13c49bec72d83..7c9e34d679d325d101f937e97ea25dfe76f79f80 100644 (file)
@@ -336,12 +336,26 @@ int ib_register_device(struct ib_device *device,
        struct device *parent = device->dev.parent;
 
        WARN_ON_ONCE(!parent);
-       if (!device->dev.dma_ops)
-               device->dev.dma_ops = parent->dma_ops;
-       if (!device->dev.dma_mask)
-               device->dev.dma_mask = parent->dma_mask;
-       if (!device->dev.coherent_dma_mask)
-               device->dev.coherent_dma_mask = parent->coherent_dma_mask;
+       WARN_ON_ONCE(device->dma_device);
+       if (device->dev.dma_ops) {
+               /*
+                * The caller provided custom DMA operations. Copy the
+                * DMA-related fields that are used by e.g. dma_alloc_coherent()
+                * into device->dev.
+                */
+               device->dma_device = &device->dev;
+               if (!device->dev.dma_mask)
+                       device->dev.dma_mask = parent->dma_mask;
+               if (!device->dev.coherent_dma_mask)
+                       device->dev.coherent_dma_mask =
+                               parent->coherent_dma_mask;
+       } else {
+               /*
+                * The caller did not provide custom DMA operations. Use the
+                * DMA mapping operations of the parent device.
+                */
+               device->dma_device = parent;
+       }
 
        mutex_lock(&device_mutex);
 
@@ -1015,8 +1029,7 @@ static int __init ib_core_init(void)
                return -ENOMEM;
 
        ib_comp_wq = alloc_workqueue("ib-comp-wq",
-                       WQ_UNBOUND | WQ_HIGHPRI | WQ_MEM_RECLAIM,
-                       WQ_UNBOUND_MAX_ACTIVE);
+                       WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
        if (!ib_comp_wq) {
                ret = -ENOMEM;
                goto err;
index 0f5d43d1f5fc30d812a6a3988d90b30cdb459da0..70c3e9e795082b7152ea754a52fc68c412dee7ca 100644 (file)
@@ -160,6 +160,9 @@ int i40iw_inetaddr_event(struct notifier_block *notifier,
                return NOTIFY_DONE;
 
        iwdev = &hdl->device;
+       if (iwdev->init_state < INET_NOTIFIER)
+               return NOTIFY_DONE;
+
        netdev = iwdev->ldev->netdev;
        upper_dev = netdev_master_upper_dev_get(netdev);
        if (netdev != event_netdev)
@@ -214,6 +217,9 @@ int i40iw_inet6addr_event(struct notifier_block *notifier,
                return NOTIFY_DONE;
 
        iwdev = &hdl->device;
+       if (iwdev->init_state < INET_NOTIFIER)
+               return NOTIFY_DONE;
+
        netdev = iwdev->ldev->netdev;
        if (netdev != event_netdev)
                return NOTIFY_DONE;
@@ -260,6 +266,8 @@ int i40iw_net_event(struct notifier_block *notifier, unsigned long event, void *
                if (!iwhdl)
                        return NOTIFY_DONE;
                iwdev = &iwhdl->device;
+               if (iwdev->init_state < INET_NOTIFIER)
+                       return NOTIFY_DONE;
                p = (__be32 *)neigh->primary_key;
                i40iw_copy_ip_ntohl(local_ipaddr, p);
                if (neigh->nud_state & NUD_VALID) {
index bc9fb144e57b8e3a05863223156f25b7f17e6a34..c52edeafd616a3be52fec913430405e5adff13d2 100644 (file)
@@ -372,7 +372,7 @@ static int _ocrdma_pd_mgr_put_bitmap(struct ocrdma_dev *dev, u16 pd_id,
        return 0;
 }
 
-static u8 ocrdma_put_pd_num(struct ocrdma_dev *dev, u16 pd_id,
+static int ocrdma_put_pd_num(struct ocrdma_dev *dev, u16 pd_id,
                                   bool dpp_pool)
 {
        int status;
index 12c4208fd7013b78c5e1bf736d82461c05c814c3..af9f596bb68b294cc587f13924a645ac70e6235c 100644 (file)
@@ -7068,7 +7068,7 @@ static void qib_7322_txchk_change(struct qib_devdata *dd, u32 start,
        unsigned long flags;
 
        while (wait) {
-               unsigned long shadow;
+               unsigned long shadow = 0;
                int cstart, previ = -1;
 
                /*
index 3cd96c1b95029d2d365279d3ccfeebe038e3a2e4..9fbe22d3467b222988cf33fee7c04f1996a84928 100644 (file)
@@ -69,6 +69,9 @@
  */
 #define PCI_DEVICE_ID_VMWARE_PVRDMA    0x0820
 
+#define PVRDMA_NUM_RING_PAGES          4
+#define PVRDMA_QP_NUM_HEADER_PAGES     1
+
 struct pvrdma_dev;
 
 struct pvrdma_page_dir {
index e69d6f3cae32b5018ea4a09efd299ec402aa4a4f..09078ccfaec719b8800ce87beaafbaa92b50cbff 100644 (file)
@@ -132,7 +132,7 @@ enum pvrdma_pci_resource {
 
 enum pvrdma_device_ctl {
        PVRDMA_DEVICE_CTL_ACTIVATE,     /* Activate device. */
-       PVRDMA_DEVICE_CTL_QUIESCE,      /* Quiesce device. */
+       PVRDMA_DEVICE_CTL_UNQUIESCE,    /* Unquiesce device. */
        PVRDMA_DEVICE_CTL_RESET,        /* Reset device. */
 };
 
index 100bea5c42ffb74375552131ebb1fbd5cbdc3659..34ebc7615411d9e3574e50fc0bf083056ef756cf 100644 (file)
@@ -56,7 +56,7 @@
 #include "pvrdma.h"
 
 #define DRV_NAME       "vmw_pvrdma"
-#define DRV_VERSION    "1.0.0.0-k"
+#define DRV_VERSION    "1.0.1.0-k"
 
 static DEFINE_MUTEX(pvrdma_device_list_lock);
 static LIST_HEAD(pvrdma_device_list);
@@ -660,7 +660,16 @@ static void pvrdma_netdevice_event_handle(struct pvrdma_dev *dev,
                pvrdma_dispatch_event(dev, 1, IB_EVENT_PORT_ERR);
                break;
        case NETDEV_UP:
-               pvrdma_dispatch_event(dev, 1, IB_EVENT_PORT_ACTIVE);
+               pvrdma_write_reg(dev, PVRDMA_REG_CTL,
+                                PVRDMA_DEVICE_CTL_UNQUIESCE);
+
+               mb();
+
+               if (pvrdma_read_reg(dev, PVRDMA_REG_ERR))
+                       dev_err(&dev->pdev->dev,
+                               "failed to activate device during link up\n");
+               else
+                       pvrdma_dispatch_event(dev, 1, IB_EVENT_PORT_ACTIVE);
                break;
        default:
                dev_dbg(&dev->pdev->dev, "ignore netdevice event %ld on %s\n",
@@ -858,7 +867,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
        dev->dsr->resp_slot_dma = (u64)slot_dma;
 
        /* Async event ring */
-       dev->dsr->async_ring_pages.num_pages = 4;
+       dev->dsr->async_ring_pages.num_pages = PVRDMA_NUM_RING_PAGES;
        ret = pvrdma_page_dir_init(dev, &dev->async_pdir,
                                   dev->dsr->async_ring_pages.num_pages, true);
        if (ret)
@@ -867,7 +876,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
        dev->dsr->async_ring_pages.pdir_dma = dev->async_pdir.dir_dma;
 
        /* CQ notification ring */
-       dev->dsr->cq_ring_pages.num_pages = 4;
+       dev->dsr->cq_ring_pages.num_pages = PVRDMA_NUM_RING_PAGES;
        ret = pvrdma_page_dir_init(dev, &dev->cq_pdir,
                                   dev->dsr->cq_ring_pages.num_pages, true);
        if (ret)
index dbbfd35e7da7ade590bc0b13784e82ba9266f213..30062aad3af1a2cfa6d14ce9bd60250644b85ab8 100644 (file)
@@ -170,8 +170,9 @@ static int pvrdma_set_sq_size(struct pvrdma_dev *dev, struct ib_qp_cap *req_cap,
                                             sizeof(struct pvrdma_sge) *
                                             qp->sq.max_sg);
        /* Note: one extra page for the header. */
-       qp->npages_send = 1 + (qp->sq.wqe_cnt * qp->sq.wqe_size +
-                              PAGE_SIZE - 1) / PAGE_SIZE;
+       qp->npages_send = PVRDMA_QP_NUM_HEADER_PAGES +
+                         (qp->sq.wqe_cnt * qp->sq.wqe_size + PAGE_SIZE - 1) /
+                                                               PAGE_SIZE;
 
        return 0;
 }
@@ -288,7 +289,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
                        qp->npages = qp->npages_send + qp->npages_recv;
 
                        /* Skip header page. */
-                       qp->sq.offset = PAGE_SIZE;
+                       qp->sq.offset = PVRDMA_QP_NUM_HEADER_PAGES * PAGE_SIZE;
 
                        /* Recv queue pages are after send pages. */
                        qp->rq.offset = qp->npages_send * PAGE_SIZE;
@@ -341,7 +342,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
        cmd->qp_type = ib_qp_type_to_pvrdma(init_attr->qp_type);
        cmd->access_flags = IB_ACCESS_LOCAL_WRITE;
        cmd->total_chunks = qp->npages;
-       cmd->send_chunks = qp->npages_send - 1;
+       cmd->send_chunks = qp->npages_send - PVRDMA_QP_NUM_HEADER_PAGES;
        cmd->pdir_dma = qp->pdir.dir_dma;
 
        dev_dbg(&dev->pdev->dev, "create queuepair with %d, %d, %d, %d\n",
@@ -554,13 +555,13 @@ out:
        return ret;
 }
 
-static inline void *get_sq_wqe(struct pvrdma_qp *qp, int n)
+static inline void *get_sq_wqe(struct pvrdma_qp *qp, unsigned int n)
 {
        return pvrdma_page_dir_get_ptr(&qp->pdir,
                                       qp->sq.offset + n * qp->sq.wqe_size);
 }
 
-static inline void *get_rq_wqe(struct pvrdma_qp *qp, int n)
+static inline void *get_rq_wqe(struct pvrdma_qp *qp, unsigned int n)
 {
        return pvrdma_page_dir_get_ptr(&qp->pdir,
                                       qp->rq.offset + n * qp->rq.wqe_size);
@@ -598,9 +599,7 @@ int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
        unsigned long flags;
        struct pvrdma_sq_wqe_hdr *wqe_hdr;
        struct pvrdma_sge *sge;
-       int i, index;
-       int nreq;
-       int ret;
+       int i, ret;
 
        /*
         * In states lower than RTS, we can fail immediately. In other states,
@@ -613,9 +612,8 @@ int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
        spin_lock_irqsave(&qp->sq.lock, flags);
 
-       index = pvrdma_idx(&qp->sq.ring->prod_tail, qp->sq.wqe_cnt);
-       for (nreq = 0; wr; nreq++, wr = wr->next) {
-               unsigned int tail;
+       while (wr) {
+               unsigned int tail = 0;
 
                if (unlikely(!pvrdma_idx_ring_has_space(
                                qp->sq.ring, qp->sq.wqe_cnt, &tail))) {
@@ -680,7 +678,7 @@ int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        }
                }
 
-               wqe_hdr = (struct pvrdma_sq_wqe_hdr *)get_sq_wqe(qp, index);
+               wqe_hdr = (struct pvrdma_sq_wqe_hdr *)get_sq_wqe(qp, tail);
                memset(wqe_hdr, 0, sizeof(*wqe_hdr));
                wqe_hdr->wr_id = wr->wr_id;
                wqe_hdr->num_sge = wr->num_sge;
@@ -771,12 +769,11 @@ int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                /* Make sure wqe is written before index update */
                smp_wmb();
 
-               index++;
-               if (unlikely(index >= qp->sq.wqe_cnt))
-                       index = 0;
                /* Update shared sq ring */
                pvrdma_idx_ring_inc(&qp->sq.ring->prod_tail,
                                    qp->sq.wqe_cnt);
+
+               wr = wr->next;
        }
 
        ret = 0;
@@ -806,7 +803,6 @@ int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
        struct pvrdma_qp *qp = to_vqp(ibqp);
        struct pvrdma_rq_wqe_hdr *wqe_hdr;
        struct pvrdma_sge *sge;
-       int index, nreq;
        int ret = 0;
        int i;
 
@@ -821,9 +817,8 @@ int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
        spin_lock_irqsave(&qp->rq.lock, flags);
 
-       index = pvrdma_idx(&qp->rq.ring->prod_tail, qp->rq.wqe_cnt);
-       for (nreq = 0; wr; nreq++, wr = wr->next) {
-               unsigned int tail;
+       while (wr) {
+               unsigned int tail = 0;
 
                if (unlikely(wr->num_sge > qp->rq.max_sg ||
                             wr->num_sge < 0)) {
@@ -843,7 +838,7 @@ int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                        goto out;
                }
 
-               wqe_hdr = (struct pvrdma_rq_wqe_hdr *)get_rq_wqe(qp, index);
+               wqe_hdr = (struct pvrdma_rq_wqe_hdr *)get_rq_wqe(qp, tail);
                wqe_hdr->wr_id = wr->wr_id;
                wqe_hdr->num_sge = wr->num_sge;
                wqe_hdr->total_len = 0;
@@ -859,12 +854,11 @@ int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                /* Make sure wqe is written before index update */
                smp_wmb();
 
-               index++;
-               if (unlikely(index >= qp->rq.wqe_cnt))
-                       index = 0;
                /* Update shared rq ring */
                pvrdma_idx_ring_inc(&qp->rq.ring->prod_tail,
                                    qp->rq.wqe_cnt);
+
+               wr = wr->next;
        }
 
        spin_unlock_irqrestore(&qp->rq.lock, flags);
index e202b8142759f58e0c06317ce1e4f3d798c54f37..6b712eecbd37d9ca5a0bf312028dc7b23c1c2fd8 100644 (file)
@@ -170,9 +170,9 @@ struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi,
 
        spin_lock_irq(&rdi->mmap_offset_lock);
        if (rdi->mmap_offset == 0)
-               rdi->mmap_offset = PAGE_SIZE;
+               rdi->mmap_offset = ALIGN(PAGE_SIZE, SHMLBA);
        ip->offset = rdi->mmap_offset;
-       rdi->mmap_offset += size;
+       rdi->mmap_offset += ALIGN(size, SHMLBA);
        spin_unlock_irq(&rdi->mmap_offset_lock);
 
        INIT_LIST_HEAD(&ip->pending_mmaps);
index 7d1ac27ed2516dad367354f36b15903cb3197ade..6332dedc11e8a3306697e494ab89996b34d453ab 100644 (file)
@@ -22,4 +22,4 @@ config RDMA_RXE
        To configure and work with soft-RoCE driver please use the
        following wiki page under "configure Soft-RoCE (RXE)" section:
 
-       https://github.com/SoftRoCE/rxe-dev/wiki/rxe-dev:-Home
+       https://github.com/linux-rdma/rdma-core/blob/master/Documentation/rxe.md
index c572a4c09359c9f91fcf7f55466fadff012fbc82..bd812e00988ed32f5517ce952a0e2186c4678f87 100644 (file)
@@ -156,10 +156,10 @@ struct rxe_mmap_info *rxe_create_mmap_info(struct rxe_dev *rxe,
        spin_lock_bh(&rxe->mmap_offset_lock);
 
        if (rxe->mmap_offset == 0)
-               rxe->mmap_offset = PAGE_SIZE;
+               rxe->mmap_offset = ALIGN(PAGE_SIZE, SHMLBA);
 
        ip->info.offset = rxe->mmap_offset;
-       rxe->mmap_offset += size;
+       rxe->mmap_offset += ALIGN(size, SHMLBA);
 
        spin_unlock_bh(&rxe->mmap_offset_lock);
 
index dbfde0dc6ff7e7bcf3c6b182b5f49fc5daf65009..9f95f50b290904fe67797cacfa5af2f565e3188d 100644 (file)
@@ -729,11 +729,11 @@ next_wqe:
        ret = rxe_xmit_packet(to_rdev(qp->ibqp.device), qp, &pkt, skb);
        if (ret) {
                qp->need_req_skb = 1;
-               kfree_skb(skb);
 
                rollback_state(wqe, qp, &rollback_wqe, rollback_psn);
 
                if (ret == -EAGAIN) {
+                       kfree_skb(skb);
                        rxe_run_task(&qp->req.task, 1);
                        goto exit;
                }
index d404a8aba7afcaf8ab8addd38949ddf5adcd0847..c9dd385ce62e2c65b97e5bf16e5d8f6288b6f19c 100644 (file)
@@ -813,18 +813,17 @@ static enum resp_states execute(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
                WARN_ON_ONCE(1);
        }
 
-       /* We successfully processed this new request. */
-       qp->resp.msn++;
-
        /* next expected psn, read handles this separately */
        qp->resp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
 
        qp->resp.opcode = pkt->opcode;
        qp->resp.status = IB_WC_SUCCESS;
 
-       if (pkt->mask & RXE_COMP_MASK)
+       if (pkt->mask & RXE_COMP_MASK) {
+               /* We successfully processed this new request. */
+               qp->resp.msn++;
                return RESPST_COMPLETE;
-       else if (qp_type(qp) == IB_QPT_RC)
+       else if (qp_type(qp) == IB_QPT_RC)
                return RESPST_ACKNOWLEDGE;
        else
                return RESPST_CLEANUP;
index 9d0b22ad58c15759c3b92472083da15af5c42bac..c1ae4aeae2f90e5a9c1376a296529d912d77d457 100644 (file)
@@ -430,6 +430,7 @@ struct iser_fr_desc {
        struct list_head                  list;
        struct iser_reg_resources         rsc;
        struct iser_pi_context           *pi_ctx;
+       struct list_head                  all_list;
 };
 
 /**
@@ -443,6 +444,7 @@ struct iser_fr_pool {
        struct list_head        list;
        spinlock_t              lock;
        int                     size;
+       struct list_head        all_list;
 };
 
 /**
index 30b622f2ab7382ca04a8affbd26dfd01ff98716c..c538a38c91ce95acf8e00fcdf43fa28588ad2f49 100644 (file)
@@ -362,6 +362,7 @@ int iser_alloc_fastreg_pool(struct ib_conn *ib_conn,
        int i, ret;
 
        INIT_LIST_HEAD(&fr_pool->list);
+       INIT_LIST_HEAD(&fr_pool->all_list);
        spin_lock_init(&fr_pool->lock);
        fr_pool->size = 0;
        for (i = 0; i < cmds_max; i++) {
@@ -373,6 +374,7 @@ int iser_alloc_fastreg_pool(struct ib_conn *ib_conn,
                }
 
                list_add_tail(&desc->list, &fr_pool->list);
+               list_add_tail(&desc->all_list, &fr_pool->all_list);
                fr_pool->size++;
        }
 
@@ -392,13 +394,13 @@ void iser_free_fastreg_pool(struct ib_conn *ib_conn)
        struct iser_fr_desc *desc, *tmp;
        int i = 0;
 
-       if (list_empty(&fr_pool->list))
+       if (list_empty(&fr_pool->all_list))
                return;
 
        iser_info("freeing conn %p fr pool\n", ib_conn);
 
-       list_for_each_entry_safe(desc, tmp, &fr_pool->list, list) {
-               list_del(&desc->list);
+       list_for_each_entry_safe(desc, tmp, &fr_pool->all_list, all_list) {
+               list_del(&desc->all_list);
                iser_free_reg_res(&desc->rsc);
                if (desc->pi_ctx)
                        iser_free_pi_ctx(desc->pi_ctx);
index d96aa27dfcdc9776260c72753b48b63691af1b04..db64adfbe1aff092b4418832c1c81cce0901e044 100644 (file)
@@ -141,6 +141,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
 
        interface = intf->cur_altsetting;
 
+       if (interface->desc.bNumEndpoints < 2)
+               return -ENODEV;
+
        epirq = &interface->endpoint[0].desc;
        epout = &interface->endpoint[1].desc;
 
index 9cc6d057c302a1753f33e9072ab5f5384f1eec40..23c191a2a0715abe9584760742327b25f058d53b 100644 (file)
@@ -700,6 +700,10 @@ static int cm109_usb_probe(struct usb_interface *intf,
        int error = -ENOMEM;
 
        interface = intf->cur_altsetting;
+
+       if (interface->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        endpoint = &interface->endpoint[0].desc;
 
        if (!usb_endpoint_is_int_in(endpoint))
index 9c0ea36913b4a98293911f62a2d649dc08a855cd..f4e8fbec6a942a8ea7a48e268b1e96f9fe458369 100644 (file)
@@ -1667,6 +1667,10 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc
                return -EINVAL;
 
        alt = pcu->ctrl_intf->cur_altsetting;
+
+       if (alt->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        pcu->ep_ctrl = &alt->endpoint[0].desc;
        pcu->max_ctrl_size = usb_endpoint_maxp(pcu->ep_ctrl);
 
index 79c964c075f14029a8072a6ad441927a0a40cf04..6e7ff9561d9261f31f919720925e12d8f1720b98 100644 (file)
@@ -875,6 +875,10 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
        int ret, pipe, i;
 
        interface = intf->cur_altsetting;
+
+       if (interface->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        endpoint = &interface->endpoint[0].desc;
        if (!usb_endpoint_is_int_in(endpoint))
                return -ENODEV;
index 72b28ebfe360030cbeeadec8a52385a9de09a7f0..f210e19ddba66b86312b09c6925c55ea9fc0fab7 100644 (file)
@@ -1282,10 +1282,8 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
        /* handle buttons */
        if (pkt_id == SS4_PACKET_ID_STICK) {
                f->ts_left = !!(SS4_BTN_V2(p) & 0x01);
-               if (!(priv->flags & ALPS_BUTTONPAD)) {
-                       f->ts_right = !!(SS4_BTN_V2(p) & 0x02);
-                       f->ts_middle = !!(SS4_BTN_V2(p) & 0x04);
-               }
+               f->ts_right = !!(SS4_BTN_V2(p) & 0x02);
+               f->ts_middle = !!(SS4_BTN_V2(p) & 0x04);
        } else {
                f->left = !!(SS4_BTN_V2(p) & 0x01);
                if (!(priv->flags & ALPS_BUTTONPAD)) {
@@ -2462,14 +2460,34 @@ static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
        int num_y_electrode;
        int x_pitch, y_pitch, x_phys, y_phys;
 
-       num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
-       num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
+       if (IS_SS4PLUS_DEV(priv->dev_id)) {
+               num_x_electrode =
+                       SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F);
+               num_y_electrode =
+                       SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F);
+
+               priv->x_max =
+                       (num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
+               priv->y_max =
+                       (num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
 
-       priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
-       priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
+               x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
+               y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM;
 
-       x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
-       y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
+       } else {
+               num_x_electrode =
+                       SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
+               num_y_electrode =
+                       SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
+
+               priv->x_max =
+                       (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
+               priv->y_max =
+                       (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
+
+               x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
+               y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
+       }
 
        x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
        y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
@@ -2485,7 +2503,10 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
 {
        unsigned char is_btnless;
 
-       is_btnless = (otp[1][1] >> 3) & 0x01;
+       if (IS_SS4PLUS_DEV(priv->dev_id))
+               is_btnless = (otp[1][0] >> 1) & 0x01;
+       else
+               is_btnless = (otp[1][1] >> 3) & 0x01;
 
        if (is_btnless)
                priv->flags |= ALPS_BUTTONPAD;
@@ -2493,6 +2514,21 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
        return 0;
 }
 
+static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
+                                      struct alps_data *priv)
+{
+       bool is_dual = false;
+
+       if (IS_SS4PLUS_DEV(priv->dev_id))
+               is_dual = (otp[0][0] >> 4) & 0x01;
+
+       if (is_dual)
+               priv->flags |= ALPS_DUALPOINT |
+                                       ALPS_DUALPOINT_WITH_PRESSURE;
+
+       return 0;
+}
+
 static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
                                    struct alps_data *priv)
 {
@@ -2508,6 +2544,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
 
        alps_update_btn_info_ss4_v2(otp, priv);
 
+       alps_update_dual_info_ss4_v2(otp, priv);
+
        return 0;
 }
 
@@ -2753,10 +2791,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
                if (alps_set_defaults_ss4_v2(psmouse, priv))
                        return -EIO;
 
-               if (priv->fw_ver[1] == 0x1)
-                       priv->flags |= ALPS_DUALPOINT |
-                                       ALPS_DUALPOINT_WITH_PRESSURE;
-
                break;
        }
 
@@ -2827,10 +2861,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
                           ec[2] >= 0x90 && ec[2] <= 0x9d) {
                        protocol = &alps_v3_protocol_data;
                } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
-                          e7[2] == 0x14 && ec[1] == 0x02) {
-                       protocol = &alps_v8_protocol_data;
-               } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
-                          e7[2] == 0x28 && ec[1] == 0x01) {
+                          (e7[2] == 0x14 || e7[2] == 0x28)) {
                        protocol = &alps_v8_protocol_data;
                } else {
                        psmouse_dbg(psmouse,
@@ -2840,7 +2871,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
        }
 
        if (priv) {
-               /* Save the Firmware version */
+               /* Save Device ID and Firmware version */
+               memcpy(priv->dev_id, e7, 3);
                memcpy(priv->fw_ver, ec, 3);
                error = alps_set_protocol(psmouse, priv, protocol);
                if (error)
index 6d279aa27cb9a10d70a2e732fe9599297883cbc0..4334f2805d93c7a3e8454a8cf0d950a14999278c 100644 (file)
@@ -54,6 +54,16 @@ enum SS4_PACKET_ID {
 
 #define SS4_MASK_NORMAL_BUTTONS                0x07
 
+#define SS4PLUS_COUNT_PER_ELECTRODE    128
+#define SS4PLUS_NUMSENSOR_XOFFSET      16
+#define SS4PLUS_NUMSENSOR_YOFFSET      5
+#define SS4PLUS_MIN_PITCH_MM           37
+
+#define IS_SS4PLUS_DEV(_b)     (((_b[0]) == 0x73) &&   \
+                                ((_b[1]) == 0x03) &&   \
+                                ((_b[2]) == 0x28)              \
+                               )
+
 #define SS4_IS_IDLE_V2(_b)     (((_b[0]) == 0x18) &&           \
                                 ((_b[1]) == 0x10) &&           \
                                 ((_b[2]) == 0x00) &&           \
@@ -283,6 +293,7 @@ struct alps_data {
        int addr_command;
        u16 proto_version;
        u8 byte0, mask0;
+       u8 dev_id[3];
        u8 fw_ver[3];
        int flags;
        int x_max;
index 352050e9031dc31ab87e7d3cdb2948b2ead7dee1..d5ab9ddef3e37eeb553307c7406adc1f2c011057 100644 (file)
@@ -218,17 +218,19 @@ static int elan_query_product(struct elan_tp_data *data)
 
 static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
 {
-       if (data->ic_type != 0x0E)
-               return false;
-
-       switch (data->product_id) {
-       case 0x05 ... 0x07:
-       case 0x09:
-       case 0x13:
+       if (data->ic_type == 0x0E) {
+               switch (data->product_id) {
+               case 0x05 ... 0x07:
+               case 0x09:
+               case 0x13:
+                       return true;
+               }
+       } else if (data->ic_type == 0x08 && data->product_id == 0x26) {
+               /* ASUS EeeBook X205TA */
                return true;
-       default:
-               return false;
        }
+
+       return false;
 }
 
 static int __elan_initialize(struct elan_tp_data *data)
index 1986786133824d5b7cc815ec98efe61afd2624e2..34dfee555b201b0577e6e5fc0c58c63e7cc8cac7 100644 (file)
@@ -170,6 +170,10 @@ static int rmi_f30_config(struct rmi_function *fn)
                                rmi_get_platform_data(fn->rmi_dev);
        int error;
 
+       /* can happen if f30_data.disable is set */
+       if (!f30)
+               return 0;
+
        if (pdata->f30_data.trackstick_buttons) {
                /* Try [re-]establish link to F03. */
                f30->f03 = rmi_find_function(fn->rmi_dev, 0x03);
index 05afd16ea9c9efc0bb52efe49510444478e1e220..312bd6ca919806f2593e12814e5037469d609c0f 100644 (file)
@@ -119,6 +119,13 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
                },
        },
+       {
+               /* Dell Embedded Box PC 3000 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),
+               },
+       },
        {
                /* OQO Model 01 */
                .matches = {
@@ -513,6 +520,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
                },
        },
+       {
+               /* TUXEDO BU1406 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"),
+               },
+       },
        { }
 };
 
index cd852059b99e81899f8436f31071c929eb470b83..df4bea96d7ed7d10e66478c929feb1094ff5f09c 100644 (file)
@@ -340,6 +340,9 @@ static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id
        int error;
        int i;
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!hanwang || !input_dev) {
index e850d7e8afbc4d22afb1bc73b2e99fc3f1cf5e8f..4d9d64908b595f9828e8e82e47e57b6b2935c07f 100644 (file)
@@ -122,6 +122,9 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct input_dev *input_dev;
        int error = -ENOMEM;
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!kbtab || !input_dev)
index aefb6e11f88a0838917b0a3b7a59dc9eae6b37f2..4c0eecae065c113a26400469d7def3c2b9bcc635 100644 (file)
@@ -527,6 +527,9 @@ static int sur40_probe(struct usb_interface *interface,
        if (iface_desc->desc.bInterfaceClass != 0xFF)
                return -ENODEV;
 
+       if (iface_desc->desc.bNumEndpoints < 5)
+               return -ENODEV;
+
        /* Use endpoint #4 (0x86). */
        endpoint = &iface_desc->endpoint[4].desc;
        if (endpoint->bEndpointAddress != TOUCH_ENDPOINT)
index 98940d1392cb0cd19d648b6a25f2a5ba36c052d4..b17536d6e69bdbf956a61d8c3dff06351a1a51df 100644 (file)
@@ -3202,7 +3202,7 @@ static void amd_iommu_get_resv_regions(struct device *dev,
 
        region = iommu_alloc_resv_region(MSI_RANGE_START,
                                         MSI_RANGE_END - MSI_RANGE_START + 1,
-                                        0, IOMMU_RESV_RESERVED);
+                                        0, IOMMU_RESV_MSI);
        if (!region)
                return;
        list_add_tail(&region->list, head);
index 5806a6acc94ecd7543c2435558a0907ec0934ff2..591bb96047c9765fd3e0fb536d3f26ca0a5f187f 100644 (file)
@@ -1888,7 +1888,7 @@ static void arm_smmu_get_resv_regions(struct device *dev,
        int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
 
        region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH,
-                                        prot, IOMMU_RESV_MSI);
+                                        prot, IOMMU_RESV_SW_MSI);
        if (!region)
                return;
 
index abf6496843a617070289377ffad3fd1e119b0aa6..b493c99e17f74de338805167c3ddb104e3354b62 100644 (file)
@@ -1608,7 +1608,7 @@ static void arm_smmu_get_resv_regions(struct device *dev,
        int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
 
        region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH,
-                                        prot, IOMMU_RESV_MSI);
+                                        prot, IOMMU_RESV_SW_MSI);
        if (!region)
                return;
 
index a7e0821c9967e490258921238e6640723e79375d..c01bfcdb238316c049ae0dd6b4bf2d43c6c61440 100644 (file)
@@ -512,7 +512,13 @@ static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
        spin_lock_irqsave(&data->lock, flags);
        if (data->active && data->version >= MAKE_MMU_VER(3, 3)) {
                clk_enable(data->clk_master);
-               __sysmmu_tlb_invalidate_entry(data, iova, 1);
+               if (sysmmu_block(data)) {
+                       if (data->version >= MAKE_MMU_VER(5, 0))
+                               __sysmmu_tlb_invalidate(data);
+                       else
+                               __sysmmu_tlb_invalidate_entry(data, iova, 1);
+                       sysmmu_unblock(data);
+               }
                clk_disable(data->clk_master);
        }
        spin_unlock_irqrestore(&data->lock, flags);
index 238ad3447712d263ef9d67a109c2d86c03693a87..d412a313a37232997d406e53379e1466d10b93e7 100644 (file)
@@ -916,7 +916,7 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf
                                 * which we used for the IOMMU lookup. Strictly speaking
                                 * we could do this for all PCI devices; we only need to
                                 * get the BDF# from the scope table for ACPI matches. */
-                               if (pdev->is_virtfn)
+                               if (pdev && pdev->is_virtfn)
                                        goto got_pdev;
 
                                *bus = drhd->devices[i].bus;
@@ -5249,7 +5249,7 @@ static void intel_iommu_get_resv_regions(struct device *device,
 
        reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
                                      IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
-                                     0, IOMMU_RESV_RESERVED);
+                                     0, IOMMU_RESV_MSI);
        if (!reg)
                return;
        list_add_tail(&reg->list, head);
index 1c049e2e12bf0ddacbc0e8ff9cbb09751996a549..8d6ca28c3e1f14a6c364aae89640ee6535f8f0d6 100644 (file)
@@ -422,8 +422,12 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, unsigned long iova,
                        pte |= ARM_V7S_ATTR_NS_TABLE;
 
                __arm_v7s_set_pte(ptep, pte, 1, cfg);
-       } else {
+       } else if (ARM_V7S_PTE_IS_TABLE(pte, lvl)) {
                cptep = iopte_deref(pte, lvl);
+       } else {
+               /* We require an unmap first */
+               WARN_ON(!selftest_running);
+               return -EEXIST;
        }
 
        /* Rinse, repeat */
index feacc54bec683b535fcba37e47ecb46af014ef5a..f9bc6ebb8140b06c845355560fd6e5d113912073 100644 (file)
@@ -335,8 +335,12 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
                if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS)
                        pte |= ARM_LPAE_PTE_NSTABLE;
                __arm_lpae_set_pte(ptep, pte, cfg);
-       } else {
+       } else if (!iopte_leaf(pte, lvl)) {
                cptep = iopte_deref(pte, data);
+       } else {
+               /* We require an unmap first */
+               WARN_ON(!selftest_running);
+               return -EEXIST;
        }
 
        /* Rinse, repeat */
index 8ea14f41a979fd4e72e3a6093e5fa8d2a0eff24a..3b67144dead2e3811918af8fa44ec6e67a19c955 100644 (file)
@@ -72,6 +72,7 @@ static const char * const iommu_group_resv_type_string[] = {
        [IOMMU_RESV_DIRECT]     = "direct",
        [IOMMU_RESV_RESERVED]   = "reserved",
        [IOMMU_RESV_MSI]        = "msi",
+       [IOMMU_RESV_SW_MSI]     = "msi",
 };
 
 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store)          \
@@ -1743,8 +1744,8 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)
 }
 
 struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start,
-                                                 size_t length,
-                                                 int prot, int type)
+                                                 size_t length, int prot,
+                                                 enum iommu_resv_type type)
 {
        struct iommu_resv_region *region;
 
index 11e13c56126fba31fca9c59d66252ffeced55c8a..2da3ff650e1d550cc50fd8572156ddd1cabd7961 100644 (file)
@@ -2317,6 +2317,9 @@ static int gigaset_probe(struct usb_interface *interface,
                return -ENODEV;
        }
 
+       if (hostif->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        dev_info(&udev->dev,
                 "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n",
                 __func__, le16_to_cpu(udev->descriptor.idVendor),
index 3f041b1870335ab48daeb847b986a274f619677b..f757cef293f86881667333f3ecc05bbd5f41a197 100644 (file)
@@ -392,6 +392,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
         * To get all the fields, copy all archdata
         */
        dev->ofdev.dev.archdata = chip->lbus.pdev->dev.archdata;
+       dev->ofdev.dev.dma_ops = chip->lbus.pdev->dev.dma_ops;
 #endif /* CONFIG_PCI */
 
 #ifdef DEBUG
index f4ffd1eb8f44c3d5c44c50277fb703545157dbcf..dfb75979e4555d806ea52a494e161d4c6f8fa86b 100644 (file)
@@ -989,26 +989,29 @@ static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule)
        struct dm_offload *o = container_of(cb, struct dm_offload, cb);
        struct bio_list list;
        struct bio *bio;
+       int i;
 
        INIT_LIST_HEAD(&o->cb.list);
 
        if (unlikely(!current->bio_list))
                return;
 
-       list = *current->bio_list;
-       bio_list_init(current->bio_list);
-
-       while ((bio = bio_list_pop(&list))) {
-               struct bio_set *bs = bio->bi_pool;
-               if (unlikely(!bs) || bs == fs_bio_set) {
-                       bio_list_add(current->bio_list, bio);
-                       continue;
+       for (i = 0; i < 2; i++) {
+               list = current->bio_list[i];
+               bio_list_init(&current->bio_list[i]);
+
+               while ((bio = bio_list_pop(&list))) {
+                       struct bio_set *bs = bio->bi_pool;
+                       if (unlikely(!bs) || bs == fs_bio_set) {
+                               bio_list_add(&current->bio_list[i], bio);
+                               continue;
+                       }
+
+                       spin_lock(&bs->rescue_lock);
+                       bio_list_add(&bs->rescue_list, bio);
+                       queue_work(bs->rescue_workqueue, &bs->rescue_work);
+                       spin_unlock(&bs->rescue_lock);
                }
-
-               spin_lock(&bs->rescue_lock);
-               bio_list_add(&bs->rescue_list, bio);
-               queue_work(bs->rescue_workqueue, &bs->rescue_work);
-               spin_unlock(&bs->rescue_lock);
        }
 }
 
index 2b13117fb918cbe27775ba61cc68c6f78e5408ff..321ecac23027804d18ded577a5c05604ec46220a 100644 (file)
@@ -777,7 +777,6 @@ static int gather_all_resync_info(struct mddev *mddev, int total_slots)
                bm_lockres->flags |= DLM_LKF_NOQUEUE;
                ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW);
                if (ret == -EAGAIN) {
-                       memset(bm_lockres->lksb.sb_lvbptr, '\0', LVB_SIZE);
                        s = read_resync_info(mddev, bm_lockres);
                        if (s) {
                                pr_info("%s:%d Resync[%llu..%llu] in progress on %d\n",
@@ -974,6 +973,7 @@ static int leave(struct mddev *mddev)
        lockres_free(cinfo->bitmap_lockres);
        unlock_all_bitmaps(mddev);
        dlm_release_lockspace(cinfo->lockspace, 2);
+       kfree(cinfo);
        return 0;
 }
 
index 548d1b8014f89e9f4b1170daff8fa677d758f39a..f6ae1d67bcd02c6b743258ef3ff6a05896828cb5 100644 (file)
@@ -440,14 +440,6 @@ void md_flush_request(struct mddev *mddev, struct bio *bio)
 }
 EXPORT_SYMBOL(md_flush_request);
 
-void md_unplug(struct blk_plug_cb *cb, bool from_schedule)
-{
-       struct mddev *mddev = cb->data;
-       md_wakeup_thread(mddev->thread);
-       kfree(cb);
-}
-EXPORT_SYMBOL(md_unplug);
-
 static inline struct mddev *mddev_get(struct mddev *mddev)
 {
        atomic_inc(&mddev->active);
@@ -1887,7 +1879,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
        }
        sb = page_address(rdev->sb_page);
        sb->data_size = cpu_to_le64(num_sectors);
-       sb->super_offset = rdev->sb_start;
+       sb->super_offset = cpu_to_le64(rdev->sb_start);
        sb->sb_csum = calc_sb_1_csum(sb);
        do {
                md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
@@ -2295,7 +2287,7 @@ static bool does_sb_need_changing(struct mddev *mddev)
        /* Check if any mddev parameters have changed */
        if ((mddev->dev_sectors != le64_to_cpu(sb->size)) ||
            (mddev->reshape_position != le64_to_cpu(sb->reshape_position)) ||
-           (mddev->layout != le64_to_cpu(sb->layout)) ||
+           (mddev->layout != le32_to_cpu(sb->layout)) ||
            (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) ||
            (mddev->chunk_sectors != le32_to_cpu(sb->chunksize)))
                return true;
@@ -6458,11 +6450,10 @@ static int set_array_info(struct mddev *mddev, mdu_array_info_t *info)
        mddev->layout        = info->layout;
        mddev->chunk_sectors = info->chunk_size >> 9;
 
-       mddev->max_disks     = MD_SB_DISKS;
-
        if (mddev->persistent) {
-               mddev->flags         = 0;
-               mddev->sb_flags         = 0;
+               mddev->max_disks = MD_SB_DISKS;
+               mddev->flags = 0;
+               mddev->sb_flags = 0;
        }
        set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 
@@ -6533,8 +6524,12 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
                        return -ENOSPC;
        }
        rv = mddev->pers->resize(mddev, num_sectors);
-       if (!rv)
-               revalidate_disk(mddev->gendisk);
+       if (!rv) {
+               if (mddev->queue) {
+                       set_capacity(mddev->gendisk, mddev->array_sectors);
+                       revalidate_disk(mddev->gendisk);
+               }
+       }
        return rv;
 }
 
index b8859cbf84b618b39ed3d92a2887e8764c403919..dde8ecb760c87113ba36d50c0d6867bc6e215f02 100644 (file)
@@ -676,16 +676,10 @@ extern void mddev_resume(struct mddev *mddev);
 extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                                   struct mddev *mddev);
 
-extern void md_unplug(struct blk_plug_cb *cb, bool from_schedule);
 extern void md_reload_sb(struct mddev *mddev, int raid_disk);
 extern void md_update_sb(struct mddev *mddev, int force);
 extern void md_kick_rdev_from_array(struct md_rdev * rdev);
 struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr);
-static inline int mddev_check_plugged(struct mddev *mddev)
-{
-       return !!blk_check_plugged(md_unplug, mddev,
-                                  sizeof(struct blk_plug_cb));
-}
 
 static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
 {
index fbc2d7851b497fec0cacd45832bbd9c9d258eaae..a34f58772022c9f40243e1d117a3473332bd76a2 100644 (file)
@@ -1027,7 +1027,7 @@ static int get_unqueued_pending(struct r1conf *conf)
 static void freeze_array(struct r1conf *conf, int extra)
 {
        /* Stop sync I/O and normal I/O and wait for everything to
-        * go quite.
+        * go quiet.
         * This is called in two situations:
         * 1) management command handlers (reshape, remove disk, quiesce).
         * 2) one normal I/O request failed.
@@ -1587,9 +1587,30 @@ static void raid1_make_request(struct mddev *mddev, struct bio *bio)
                        split = bio;
                }
 
-               if (bio_data_dir(split) == READ)
+               if (bio_data_dir(split) == READ) {
                        raid1_read_request(mddev, split);
-               else
+
+                       /*
+                        * If a bio is splitted, the first part of bio will
+                        * pass barrier but the bio is queued in
+                        * current->bio_list (see generic_make_request). If
+                        * there is a raise_barrier() called here, the second
+                        * part of bio can't pass barrier. But since the first
+                        * part bio isn't dispatched to underlaying disks yet,
+                        * the barrier is never released, hence raise_barrier
+                        * will alays wait. We have a deadlock.
+                        * Note, this only happens in read path. For write
+                        * path, the first part of bio is dispatched in a
+                        * schedule() call (because of blk plug) or offloaded
+                        * to raid10d.
+                        * Quitting from the function immediately can change
+                        * the bio order queued in bio_list and avoid the deadlock.
+                        */
+                       if (split != bio) {
+                               generic_make_request(bio);
+                               break;
+                       }
+               } else
                        raid1_write_request(mddev, split);
        } while (split != bio);
 }
@@ -3246,8 +3267,6 @@ static int raid1_resize(struct mddev *mddev, sector_t sectors)
                        return ret;
        }
        md_set_array_sectors(mddev, newsize);
-       set_capacity(mddev->gendisk, mddev->array_sectors);
-       revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors &&
            mddev->recovery_cp > mddev->dev_sectors) {
                mddev->recovery_cp = mddev->dev_sectors;
index 063c43d83b72c2f0f753edb7b08f8dd608fa15ad..e89a8d78a9ed537f417c414b2081ef5f9a97f291 100644 (file)
@@ -974,7 +974,8 @@ static void wait_barrier(struct r10conf *conf)
                                    !conf->barrier ||
                                    (atomic_read(&conf->nr_pending) &&
                                     current->bio_list &&
-                                    !bio_list_empty(current->bio_list)),
+                                    (!bio_list_empty(&current->bio_list[0]) ||
+                                     !bio_list_empty(&current->bio_list[1]))),
                                    conf->resync_lock);
                conf->nr_waiting--;
                if (!conf->nr_waiting)
@@ -1477,11 +1478,24 @@ retry_write:
                        mbio->bi_bdev = (void*)rdev;
 
                        atomic_inc(&r10_bio->remaining);
+
+                       cb = blk_check_plugged(raid10_unplug, mddev,
+                                              sizeof(*plug));
+                       if (cb)
+                               plug = container_of(cb, struct raid10_plug_cb,
+                                                   cb);
+                       else
+                               plug = NULL;
                        spin_lock_irqsave(&conf->device_lock, flags);
-                       bio_list_add(&conf->pending_bio_list, mbio);
-                       conf->pending_count++;
+                       if (plug) {
+                               bio_list_add(&plug->pending, mbio);
+                               plug->pending_cnt++;
+                       } else {
+                               bio_list_add(&conf->pending_bio_list, mbio);
+                               conf->pending_count++;
+                       }
                        spin_unlock_irqrestore(&conf->device_lock, flags);
-                       if (!mddev_check_plugged(mddev))
+                       if (!plug)
                                md_wakeup_thread(mddev->thread);
                }
        }
@@ -1571,7 +1585,25 @@ static void raid10_make_request(struct mddev *mddev, struct bio *bio)
                        split = bio;
                }
 
+               /*
+                * If a bio is splitted, the first part of bio will pass
+                * barrier but the bio is queued in current->bio_list (see
+                * generic_make_request). If there is a raise_barrier() called
+                * here, the second part of bio can't pass barrier. But since
+                * the first part bio isn't dispatched to underlaying disks
+                * yet, the barrier is never released, hence raise_barrier will
+                * alays wait. We have a deadlock.
+                * Note, this only happens in read path. For write path, the
+                * first part of bio is dispatched in a schedule() call
+                * (because of blk plug) or offloaded to raid10d.
+                * Quitting from the function immediately can change the bio
+                * order queued in bio_list and avoid the deadlock.
+                */
                __make_request(mddev, split);
+               if (split != bio && bio_data_dir(bio) == READ) {
+                       generic_make_request(bio);
+                       break;
+               }
        } while (split != bio);
 
        /* In case raid10d snuck in to freeze_array */
@@ -3943,10 +3975,6 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
                        return ret;
        }
        md_set_array_sectors(mddev, size);
-       if (mddev->queue) {
-               set_capacity(mddev->gendisk, mddev->array_sectors);
-               revalidate_disk(mddev->gendisk);
-       }
        if (sectors > mddev->dev_sectors &&
            mddev->recovery_cp > oldsize) {
                mddev->recovery_cp = oldsize;
index 4fb09b3fcb410468a9b1939b93d9529e70dd592d..ed5cd705b985f13611d26b44e81aefbb0e93c306 100644 (file)
@@ -1401,7 +1401,8 @@ static int set_syndrome_sources(struct page **srcs,
                     (test_bit(R5_Wantdrain, &dev->flags) ||
                      test_bit(R5_InJournal, &dev->flags))) ||
                    (srctype == SYNDROME_SRC_WRITTEN &&
-                    dev->written)) {
+                    (dev->written ||
+                     test_bit(R5_InJournal, &dev->flags)))) {
                        if (test_bit(R5_InJournal, &dev->flags))
                                srcs[slot] = sh->dev[i].orig_page;
                        else
@@ -7605,8 +7606,6 @@ static int raid5_resize(struct mddev *mddev, sector_t sectors)
                        return ret;
        }
        md_set_array_sectors(mddev, newsize);
-       set_capacity(mddev->gendisk, mddev->array_sectors);
-       revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors &&
            mddev->recovery_cp > mddev->dev_sectors) {
                mddev->recovery_cp = mddev->dev_sectors;
index 67fd8ffa60a418f6538d6b358c3e3d91f4f385b6..669a4c82f1ffa4c79b5e47173536faedecf52c34 100644 (file)
@@ -321,7 +321,7 @@ static const struct of_device_id vdoa_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, vdoa_dt_ids);
 
-static const struct platform_driver vdoa_driver = {
+static struct platform_driver vdoa_driver = {
        .probe          = vdoa_probe,
        .remove         = vdoa_remove,
        .driver         = {
index cbb03768f5d73574b4d95939a08d7605e94dd6d7..0f0c389f889713ad024eda400ea1f70799710dae 100644 (file)
@@ -861,9 +861,7 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
 
        if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) ||
                (frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) ||
-               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) ||
                (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) ||
-               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) ||
                (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M))
                swap(addr->cb, addr->cr);
 
index 823608112d89c14272c9ca2f5f8ebf46ffd30383..7918b928f0589b59b52c17c8470c3e3159d33c1e 100644 (file)
@@ -632,8 +632,8 @@ static int bdisp_open(struct file *file)
 
 error_ctrls:
        bdisp_ctrls_delete(ctx);
-error_fh:
        v4l2_fh_del(&ctx->fh);
+error_fh:
        v4l2_fh_exit(&ctx->fh);
        bdisp_hw_free_nodes(ctx);
 mem_ctx:
index ab9866024ec7983d597efd157476820222ad8134..04033efe7ad5394d4fd9493ce6b790de1404666b 100644 (file)
@@ -36,16 +36,18 @@ static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 le
 int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
 {
        struct hexline *hx;
-       u8 reset;
-       int ret,pos=0;
+       u8 *buf;
+       int ret, pos = 0;
+       u16 cpu_cs_register = cypress[type].cpu_cs_register;
 
-       hx = kmalloc(sizeof(*hx), GFP_KERNEL);
-       if (!hx)
+       buf = kmalloc(sizeof(*hx), GFP_KERNEL);
+       if (!buf)
                return -ENOMEM;
+       hx = (struct hexline *)buf;
 
        /* stop the CPU */
-       reset = 1;
-       if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+       buf[0] = 1;
+       if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1)
                err("could not stop the USB controller CPU.");
 
        while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) {
@@ -61,21 +63,21 @@ int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw
        }
        if (ret < 0) {
                err("firmware download failed at %d with %d",pos,ret);
-               kfree(hx);
+               kfree(buf);
                return ret;
        }
 
        if (ret == 0) {
                /* restart the CPU */
-               reset = 0;
-               if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
+               buf[0] = 0;
+               if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) {
                        err("could not restart the USB controller CPU.");
                        ret = -EINVAL;
                }
        } else
                ret = -EIO;
 
-       kfree(hx);
+       kfree(buf);
 
        return ret;
 }
index 5457c361ad586424050c98958bdefd22a4c17db7..bf0fe0137dfed2c893001abb8cfe8b83861dae08 100644 (file)
@@ -1947,9 +1947,7 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
        if (!of_property_read_u32(child, "dma-channel", &val))
                gpmc_onenand_data->dma_channel = val;
 
-       gpmc_onenand_init(gpmc_onenand_data);
-
-       return 0;
+       return gpmc_onenand_init(gpmc_onenand_data);
 }
 #else
 static int gpmc_probe_onenand_child(struct platform_device *pdev,
index 91f645992c9416ab07e765a05c006143fb15a17f..b27ea98b781f77747c010f90f20d9da6883a3070 100644 (file)
@@ -1792,15 +1792,14 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
 
        /* If we're permanently dead, give up. */
        if (state == pci_channel_io_perm_failure) {
-               /* Tell the AFU drivers; but we don't care what they
-                * say, we're going away.
-                */
                for (i = 0; i < adapter->slices; i++) {
                        afu = adapter->afu[i];
-                       /* Only participate in EEH if we are on a virtual PHB */
-                       if (afu->phb == NULL)
-                               return PCI_ERS_RESULT_NONE;
-                       cxl_vphb_error_detected(afu, state);
+                       /*
+                        * Tell the AFU drivers; but we don't care what they
+                        * say, we're going away.
+                        */
+                       if (afu->phb != NULL)
+                               cxl_vphb_error_detected(afu, state);
                }
                return PCI_ERS_RESULT_DISCONNECT;
        }
index 1621fa08e2069298f6a8438c8babdf11ae4a817c..ff3da960c4736147b2c1348681412953508ac49b 100644 (file)
@@ -1560,11 +1560,8 @@ static bool mmc_blk_rw_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
                               struct mmc_blk_request *brq, struct request *req,
                               bool old_req_pending)
 {
-       struct mmc_queue_req *mq_rq;
        bool req_pending;
 
-       mq_rq = container_of(brq, struct mmc_queue_req, brq);
-
        /*
         * If this is an SD card and we're writing, we can first
         * mark the known good sectors as ok.
@@ -1701,7 +1698,8 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req)
                case MMC_BLK_CMD_ERR:
                        req_pending = mmc_blk_rw_cmd_err(md, card, brq, old_req, req_pending);
                        if (mmc_blk_reset(md, card->host, type)) {
-                               mmc_blk_rw_cmd_abort(card, old_req);
+                               if (req_pending)
+                                       mmc_blk_rw_cmd_abort(card, old_req);
                                mmc_blk_rw_try_restart(mq, new_req);
                                return;
                        }
@@ -1817,6 +1815,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                mmc_blk_issue_flush(mq, req);
        } else {
                mmc_blk_issue_rw_rq(mq, req);
+               card->host->context_info.is_waiting_last_req = false;
        }
 
 out:
index 7fd722868875f396e3e4e8147774913ab860b0e2..b502601df228156c60e03e3ddabd64006bd515f7 100644 (file)
@@ -1730,7 +1730,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_select_hs400(card);
                if (err)
                        goto free_card;
-       } else {
+       } else if (!mmc_card_hs400es(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
                if (err > 0 && mmc_card_hs(card)) {
index 8e32580c12b520017eb73af884f1b04607c3a78b..b235d8da0602a84e78ff8a4478016f642c67bf43 100644 (file)
@@ -580,7 +580,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
                }
        }
        sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
-                       (mode << 8) | (div % 0xff));
+                     (mode << 8) | div);
        sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
        while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
                cpu_relax();
@@ -1559,7 +1559,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
        host->src_clk_freq = clk_get_rate(host->src_clk);
        /* Set host parameters to mmc */
        mmc->ops = &mt_msdc_ops;
-       mmc->f_min = host->src_clk_freq / (4 * 255);
+       mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 255);
 
        mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
        /* MMC core transfer sizes tunable parameters */
index 410a55b1c25fe5f2ef32ff8f2d26c4c3286f4b71..1cfd7f90033944c6a6441aaf7256b1ce44350354 100644 (file)
 #include "sdhci-pltfm.h"
 #include <linux/of.h>
 
-#define SDHCI_ARASAN_CLK_CTRL_OFFSET   0x2c
 #define SDHCI_ARASAN_VENDOR_REGISTER   0x78
 
 #define VENDOR_ENHANCED_STROBE         BIT(0)
-#define CLK_CTRL_TIMEOUT_SHIFT         16
-#define CLK_CTRL_TIMEOUT_MASK          (0xf << CLK_CTRL_TIMEOUT_SHIFT)
-#define CLK_CTRL_TIMEOUT_MIN_EXP       13
 
 #define PHY_CLK_TOO_SLOW_HZ            400000
 
@@ -163,15 +159,15 @@ static int sdhci_arasan_syscon_write(struct sdhci_host *host,
 
 static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
 {
-       u32 div;
        unsigned long freq;
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 
-       div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET);
-       div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT;
+       /* SDHCI timeout clock is in kHz */
+       freq = DIV_ROUND_UP(clk_get_rate(pltfm_host->clk), 1000);
 
-       freq = clk_get_rate(pltfm_host->clk);
-       freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div);
+       /* or in MHz */
+       if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
+               freq = DIV_ROUND_UP(freq, 1000);
 
        return freq;
 }
index 2f9ad213377a2ccb9091693ba749266fa4b420c4..7fd964256faa7d5197777fb9c513401d36f53068 100644 (file)
@@ -85,11 +85,30 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
        sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 }
 
+/*
+ * In this specific implementation of the SDHCI controller, the power register
+ * needs to have a valid voltage set even when the power supply is managed by
+ * an external regulator.
+ */
+static void sdhci_at91_set_power(struct sdhci_host *host, unsigned char mode,
+                    unsigned short vdd)
+{
+       if (!IS_ERR(host->mmc->supply.vmmc)) {
+               struct mmc_host *mmc = host->mmc;
+
+               spin_unlock_irq(&host->lock);
+               mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+               spin_lock_irq(&host->lock);
+       }
+       sdhci_set_power_noreg(host, mode, vdd);
+}
+
 static const struct sdhci_ops sdhci_at91_sama5d2_ops = {
        .set_clock              = sdhci_at91_set_clock,
        .set_bus_width          = sdhci_set_bus_width,
        .reset                  = sdhci_reset,
        .set_uhs_signaling      = sdhci_set_uhs_signaling,
+       .set_power              = sdhci_at91_set_power,
 };
 
 static const struct sdhci_pltfm_data soc_data_sama5d2 = {
index 982b3e349426141710abef87f75819c518bf4a45..86560d590786f3f62a65c8668f2e601fd27b75be 100644 (file)
@@ -451,6 +451,8 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,
        if (mode == MMC_POWER_OFF)
                return;
 
+       spin_unlock_irq(&host->lock);
+
        /*
         * Bus power might not enable after D3 -> D0 transition due to the
         * present state not yet having propagated. Retry for up to 2ms.
@@ -463,6 +465,8 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,
                reg |= SDHCI_POWER_ON;
                sdhci_writeb(host, reg, SDHCI_POWER_CONTROL);
        }
+
+       spin_lock_irq(&host->lock);
 }
 
 static const struct sdhci_ops sdhci_intel_byt_ops = {
index 6fdd7a70f229b8bfd08f6d8b9df509dd0fec2bbd..9c1a099afbbeca1c3764e7ac912af8b1fc345a20 100644 (file)
@@ -1362,7 +1362,9 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
                        return;
                }
                timeout--;
-               mdelay(1);
+               spin_unlock_irq(&host->lock);
+               usleep_range(900, 1100);
+               spin_lock_irq(&host->lock);
        }
 
        clk |= SDHCI_CLOCK_CARD_EN;
index d2c386f09d69f4edd20b0ac778624b40f826f1e3..1d843357422e8a398590aa1bcd883ab644b5d56e 100644 (file)
@@ -426,6 +426,9 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
        struct ushc_data *ushc;
        int ret;
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev);
        if (mmc == NULL)
                return -ENOMEM;
index 8a280e7d66bddc998763288a5756b2ae6a7f70bc..127adbeefb105cc031f3782b534d175f29fb7143 100644 (file)
 #define XP_ECC_CNT1_DESC_DED_WIDTH             8
 #define XP_ECC_CNT1_DESC_SEC_INDEX             0
 #define XP_ECC_CNT1_DESC_SEC_WIDTH             8
-#define XP_ECC_IER_DESC_DED_INDEX              0
+#define XP_ECC_IER_DESC_DED_INDEX              5
 #define XP_ECC_IER_DESC_DED_WIDTH              1
-#define XP_ECC_IER_DESC_SEC_INDEX              1
+#define XP_ECC_IER_DESC_SEC_INDEX              4
 #define XP_ECC_IER_DESC_SEC_WIDTH              1
-#define XP_ECC_IER_RX_DED_INDEX                        2
+#define XP_ECC_IER_RX_DED_INDEX                        3
 #define XP_ECC_IER_RX_DED_WIDTH                        1
-#define XP_ECC_IER_RX_SEC_INDEX                        3
+#define XP_ECC_IER_RX_SEC_INDEX                        2
 #define XP_ECC_IER_RX_SEC_WIDTH                        1
-#define XP_ECC_IER_TX_DED_INDEX                        4
+#define XP_ECC_IER_TX_DED_INDEX                        1
 #define XP_ECC_IER_TX_DED_WIDTH                        1
-#define XP_ECC_IER_TX_SEC_INDEX                        5
+#define XP_ECC_IER_TX_SEC_INDEX                        0
 #define XP_ECC_IER_TX_SEC_WIDTH                        1
-#define XP_ECC_ISR_DESC_DED_INDEX              0
+#define XP_ECC_ISR_DESC_DED_INDEX              5
 #define XP_ECC_ISR_DESC_DED_WIDTH              1
-#define XP_ECC_ISR_DESC_SEC_INDEX              1
+#define XP_ECC_ISR_DESC_SEC_INDEX              4
 #define XP_ECC_ISR_DESC_SEC_WIDTH              1
-#define XP_ECC_ISR_RX_DED_INDEX                        2
+#define XP_ECC_ISR_RX_DED_INDEX                        3
 #define XP_ECC_ISR_RX_DED_WIDTH                        1
-#define XP_ECC_ISR_RX_SEC_INDEX                        3
+#define XP_ECC_ISR_RX_SEC_INDEX                        2
 #define XP_ECC_ISR_RX_SEC_WIDTH                        1
-#define XP_ECC_ISR_TX_DED_INDEX                        4
+#define XP_ECC_ISR_TX_DED_INDEX                        1
 #define XP_ECC_ISR_TX_DED_WIDTH                        1
-#define XP_ECC_ISR_TX_SEC_INDEX                        5
+#define XP_ECC_ISR_TX_SEC_INDEX                        0
 #define XP_ECC_ISR_TX_SEC_WIDTH                        1
 #define XP_I2C_MUTEX_BUSY_INDEX                        31
 #define XP_I2C_MUTEX_BUSY_WIDTH                        1
 #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH   1
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX   1
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH   1
-#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX  2
-#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH  1
+#define RX_PACKET_ATTRIBUTES_LAST_INDEX                2
+#define RX_PACKET_ATTRIBUTES_LAST_WIDTH                1
 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX        3
 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH        1
 #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX     4
 #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH   1
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX    6
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH    1
+#define RX_PACKET_ATTRIBUTES_FIRST_INDEX       7
+#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH       1
 
 #define RX_NORMAL_DESC0_OVT_INDEX              0
 #define RX_NORMAL_DESC0_OVT_WIDTH              16
index 937f37a5dcb2cded9963b3732bddb08557ad50ba..24a687ce4388182716438770c49e2dca7ff81114 100644 (file)
@@ -1896,10 +1896,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
 
        /* Get the header length */
        if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) {
+               XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+                              FIRST, 1);
                rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
                                                      RX_NORMAL_DESC2, HL);
                if (rdata->rx.hdr_len)
                        pdata->ext_stats.rx_split_header_packets++;
+       } else {
+               XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+                              FIRST, 0);
        }
 
        /* Get the RSS hash */
@@ -1922,19 +1927,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
                }
        }
 
-       /* Get the packet length */
-       rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
-
-       if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
-               /* Not all the data has been transferred for this packet */
-               XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
-                              INCOMPLETE, 1);
+       /* Not all the data has been transferred for this packet */
+       if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD))
                return 0;
-       }
 
        /* This is the last of the data for this packet */
        XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
-                      INCOMPLETE, 0);
+                      LAST, 1);
+
+       /* Get the packet length */
+       rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
 
        /* Set checksum done indicator as appropriate */
        if (netdev->features & NETIF_F_RXCSUM)
index 248f60d171a5a0ce76744a95e2d59039939e6538..a713abd9d03e63aea8aab96c4f5569d1d6b3e44d 100644 (file)
@@ -1971,13 +1971,12 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
 {
        struct sk_buff *skb;
        u8 *packet;
-       unsigned int copy_len;
 
        skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len);
        if (!skb)
                return NULL;
 
-       /* Start with the header buffer which may contain just the header
+       /* Pull in the header buffer which may contain just the header
         * or the header plus data
         */
        dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base,
@@ -1986,30 +1985,49 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
 
        packet = page_address(rdata->rx.hdr.pa.pages) +
                 rdata->rx.hdr.pa.pages_offset;
-       copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len;
-       copy_len = min(rdata->rx.hdr.dma_len, copy_len);
-       skb_copy_to_linear_data(skb, packet, copy_len);
-       skb_put(skb, copy_len);
-
-       len -= copy_len;
-       if (len) {
-               /* Add the remaining data as a frag */
-               dma_sync_single_range_for_cpu(pdata->dev,
-                                             rdata->rx.buf.dma_base,
-                                             rdata->rx.buf.dma_off,
-                                             rdata->rx.buf.dma_len,
-                                             DMA_FROM_DEVICE);
-
-               skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-                               rdata->rx.buf.pa.pages,
-                               rdata->rx.buf.pa.pages_offset,
-                               len, rdata->rx.buf.dma_len);
-               rdata->rx.buf.pa.pages = NULL;
-       }
+       skb_copy_to_linear_data(skb, packet, len);
+       skb_put(skb, len);
 
        return skb;
 }
 
+static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata,
+                                    struct xgbe_packet_data *packet)
+{
+       /* Always zero if not the first descriptor */
+       if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST))
+               return 0;
+
+       /* First descriptor with split header, return header length */
+       if (rdata->rx.hdr_len)
+               return rdata->rx.hdr_len;
+
+       /* First descriptor but not the last descriptor and no split header,
+        * so the full buffer was used
+        */
+       if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST))
+               return rdata->rx.hdr.dma_len;
+
+       /* First descriptor and last descriptor and no split header, so
+        * calculate how much of the buffer was used
+        */
+       return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len);
+}
+
+static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata,
+                                    struct xgbe_packet_data *packet,
+                                    unsigned int len)
+{
+       /* Always the full buffer if not the last descriptor */
+       if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST))
+               return rdata->rx.buf.dma_len;
+
+       /* Last descriptor so calculate how much of the buffer was used
+        * for the last bit of data
+        */
+       return rdata->rx.len - len;
+}
+
 static int xgbe_tx_poll(struct xgbe_channel *channel)
 {
        struct xgbe_prv_data *pdata = channel->pdata;
@@ -2092,8 +2110,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
        struct napi_struct *napi;
        struct sk_buff *skb;
        struct skb_shared_hwtstamps *hwtstamps;
-       unsigned int incomplete, error, context_next, context;
-       unsigned int len, rdesc_len, max_len;
+       unsigned int last, error, context_next, context;
+       unsigned int len, buf1_len, buf2_len, max_len;
        unsigned int received = 0;
        int packet_count = 0;
 
@@ -2103,7 +2121,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
        if (!ring)
                return 0;
 
-       incomplete = 0;
+       last = 0;
        context_next = 0;
 
        napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi;
@@ -2137,9 +2155,8 @@ read_again:
                received++;
                ring->cur++;
 
-               incomplete = XGMAC_GET_BITS(packet->attributes,
-                                           RX_PACKET_ATTRIBUTES,
-                                           INCOMPLETE);
+               last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+                                     LAST);
                context_next = XGMAC_GET_BITS(packet->attributes,
                                              RX_PACKET_ATTRIBUTES,
                                              CONTEXT_NEXT);
@@ -2148,7 +2165,7 @@ read_again:
                                         CONTEXT);
 
                /* Earlier error, just drain the remaining data */
-               if ((incomplete || context_next) && error)
+               if ((!last || context_next) && error)
                        goto read_again;
 
                if (error || packet->errors) {
@@ -2160,16 +2177,22 @@ read_again:
                }
 
                if (!context) {
-                       /* Length is cumulative, get this descriptor's length */
-                       rdesc_len = rdata->rx.len - len;
-                       len += rdesc_len;
+                       /* Get the data length in the descriptor buffers */
+                       buf1_len = xgbe_rx_buf1_len(rdata, packet);
+                       len += buf1_len;
+                       buf2_len = xgbe_rx_buf2_len(rdata, packet, len);
+                       len += buf2_len;
 
-                       if (rdesc_len && !skb) {
+                       if (!skb) {
                                skb = xgbe_create_skb(pdata, napi, rdata,
-                                                     rdesc_len);
-                               if (!skb)
+                                                     buf1_len);
+                               if (!skb) {
                                        error = 1;
-                       } else if (rdesc_len) {
+                                       goto skip_data;
+                               }
+                       }
+
+                       if (buf2_len) {
                                dma_sync_single_range_for_cpu(pdata->dev,
                                                        rdata->rx.buf.dma_base,
                                                        rdata->rx.buf.dma_off,
@@ -2179,13 +2202,14 @@ read_again:
                                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
                                                rdata->rx.buf.pa.pages,
                                                rdata->rx.buf.pa.pages_offset,
-                                               rdesc_len,
+                                               buf2_len,
                                                rdata->rx.buf.dma_len);
                                rdata->rx.buf.pa.pages = NULL;
                        }
                }
 
-               if (incomplete || context_next)
+skip_data:
+               if (!last || context_next)
                        goto read_again;
 
                if (!skb)
@@ -2243,7 +2267,7 @@ next_packet:
        }
 
        /* Check if we need to save state before leaving */
-       if (received && (incomplete || context_next)) {
+       if (received && (!last || context_next)) {
                rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
                rdata->state_saved = 1;
                rdata->state.skb = skb;
@@ -2272,10 +2296,7 @@ static int xgbe_one_poll(struct napi_struct *napi, int budget)
        processed = xgbe_rx_poll(channel, budget);
 
        /* If we processed everything, we are done */
-       if (processed < budget) {
-               /* Turn off polling */
-               napi_complete_done(napi, processed);
-
+       if ((processed < budget) && napi_complete_done(napi, processed)) {
                /* Enable Tx and Rx interrupts */
                if (pdata->channel_irq_mode)
                        xgbe_enable_rx_tx_int(pdata, channel);
@@ -2317,10 +2338,7 @@ static int xgbe_all_poll(struct napi_struct *napi, int budget)
        } while ((processed < budget) && (processed != last_processed));
 
        /* If we processed everything, we are done */
-       if (processed < budget) {
-               /* Turn off polling */
-               napi_complete_done(napi, processed);
-
+       if ((processed < budget) && napi_complete_done(napi, processed)) {
                /* Enable Tx and Rx interrupts */
                xgbe_enable_rx_tx_ints(pdata);
        }
index dad63623be6a93672974fb43ee50b518fff59ab5..d05fbfdce5e52e640042f36ba3eb831a3a42ce8a 100644 (file)
@@ -98,6 +98,7 @@ static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
 
        if (err < 0)
                goto err_exit;
+       ndev->mtu = new_mtu;
 
        if (netif_running(ndev)) {
                aq_ndev_close(ndev);
index 581de71a958a3519682272a49dec55432e9eebed..4c6c882c6a1c424238473ea40ecf9f0ebf7cee28 100644 (file)
@@ -213,9 +213,9 @@ void aq_pci_func_free_irqs(struct aq_pci_func_s *self)
                if (!((1U << i) & self->msix_entry_mask))
                        continue;
 
-               free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]);
                if (pdev->msix_enabled)
                        irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
+               free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]);
                self->msix_entry_mask &= ~(1U << i);
        }
 }
index 1093ea18823a32fc6cb441ab45b0b3a9a82fecc2..0592a0330cf0d601f4b9a27f0d349aeccc66f833 100644 (file)
@@ -137,6 +137,7 @@ static struct aq_hw_caps_s hw_atl_a0_hw_caps_ = {
        .tx_rings = HW_ATL_A0_TX_RINGS,
        .rx_rings = HW_ATL_A0_RX_RINGS,
        .hw_features = NETIF_F_HW_CSUM |
+                       NETIF_F_RXCSUM |
                        NETIF_F_RXHASH |
                        NETIF_F_SG |
                        NETIF_F_TSO,
index 8bdee3ddd5a0bd9044063caf5686fefcc6b5465f..f3957e9303405c3f26c9f7f7d6507009d5804534 100644 (file)
@@ -188,6 +188,7 @@ static struct aq_hw_caps_s hw_atl_b0_hw_caps_ = {
        .tx_rings = HW_ATL_B0_TX_RINGS,
        .rx_rings = HW_ATL_B0_RX_RINGS,
        .hw_features = NETIF_F_HW_CSUM |
+                       NETIF_F_RXCSUM |
                        NETIF_F_RXHASH |
                        NETIF_F_SG |
                        NETIF_F_TSO |
index d8d06fdfc42b9d685244513c1542b69bd78d7ca9..ac76fc251d268e4ec5f9ca2904345557fb2cd55a 100644 (file)
@@ -13292,17 +13292,15 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
        dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
 
-       /* VF with OLD Hypervisor or old PF do not support filtering */
        if (IS_PF(bp)) {
                if (chip_is_e1x)
                        bp->accept_any_vlan = true;
                else
                        dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-#ifdef CONFIG_BNX2X_SRIOV
-       } else if (bp->acquire_resp.pfdev_info.pf_cap & PFVF_CAP_VLAN_FILTER) {
-               dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-#endif
        }
+       /* For VF we'll know whether to enable VLAN filtering after
+        * getting a response to CHANNEL_TLV_ACQUIRE from PF.
+        */
 
        dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
        dev->features |= NETIF_F_HIGHDMA;
@@ -13738,7 +13736,7 @@ static int bnx2x_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
        if (!netif_running(bp->dev)) {
                DP(BNX2X_MSG_PTP,
                   "PTP adjfreq called while the interface is down\n");
-               return -EFAULT;
+               return -ENETDOWN;
        }
 
        if (ppb < 0) {
@@ -13797,6 +13795,12 @@ static int bnx2x_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 {
        struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info);
 
+       if (!netif_running(bp->dev)) {
+               DP(BNX2X_MSG_PTP,
+                  "PTP adjtime called while the interface is down\n");
+               return -ENETDOWN;
+       }
+
        DP(BNX2X_MSG_PTP, "PTP adjtime called, delta = %llx\n", delta);
 
        timecounter_adjtime(&bp->timecounter, delta);
@@ -13809,6 +13813,12 @@ static int bnx2x_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
        struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info);
        u64 ns;
 
+       if (!netif_running(bp->dev)) {
+               DP(BNX2X_MSG_PTP,
+                  "PTP gettime called while the interface is down\n");
+               return -ENETDOWN;
+       }
+
        ns = timecounter_read(&bp->timecounter);
 
        DP(BNX2X_MSG_PTP, "PTP gettime called, ns = %llu\n", ns);
@@ -13824,6 +13834,12 @@ static int bnx2x_ptp_settime(struct ptp_clock_info *ptp,
        struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info);
        u64 ns;
 
+       if (!netif_running(bp->dev)) {
+               DP(BNX2X_MSG_PTP,
+                  "PTP settime called while the interface is down\n");
+               return -ENETDOWN;
+       }
+
        ns = timespec64_to_ns(ts);
 
        DP(BNX2X_MSG_PTP, "PTP settime called, ns = %llu\n", ns);
@@ -13991,6 +14007,14 @@ static int bnx2x_init_one(struct pci_dev *pdev,
                rc = bnx2x_vfpf_acquire(bp, tx_count, rx_count);
                if (rc)
                        goto init_one_freemem;
+
+#ifdef CONFIG_BNX2X_SRIOV
+               /* VF with OLD Hypervisor or old PF do not support filtering */
+               if (bp->acquire_resp.pfdev_info.pf_cap & PFVF_CAP_VLAN_FILTER) {
+                       dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+                       dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+               }
+#endif
        }
 
        /* Enable SRIOV if capability found in configuration space */
index 6fad22adbbb9e72fda1208d2b689ef371ac77d09..bdfd53b46bc568286ac9debc70bb14563329040b 100644 (file)
@@ -434,7 +434,9 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
 
        /* Add/Remove the filter */
        rc = bnx2x_config_vlan_mac(bp, &ramrod);
-       if (rc && rc != -EEXIST) {
+       if (rc == -EEXIST)
+               return 0;
+       if (rc) {
                BNX2X_ERR("Failed to %s %s\n",
                          filter->add ? "add" : "delete",
                          (filter->type == BNX2X_VF_FILTER_VLAN_MAC) ?
@@ -444,6 +446,8 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
                return rc;
        }
 
+       filter->applied = true;
+
        return 0;
 }
 
@@ -469,8 +473,10 @@ int bnx2x_vf_mac_vlan_config_list(struct bnx2x *bp, struct bnx2x_virtf *vf,
        /* Rollback if needed */
        if (i != filters->count) {
                BNX2X_ERR("Managed only %d/%d filters - rolling back\n",
-                         i, filters->count + 1);
+                         i, filters->count);
                while (--i >= 0) {
+                       if (!filters->filters[i].applied)
+                               continue;
                        filters->filters[i].add = !filters->filters[i].add;
                        bnx2x_vf_mac_vlan_config(bp, vf, qid,
                                                 &filters->filters[i],
@@ -1899,7 +1905,8 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)
                        continue;
                }
 
-               DP(BNX2X_MSG_IOV, "add addresses for vf %d\n", vf->abs_vfid);
+               DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
+                      "add addresses for vf %d\n", vf->abs_vfid);
                for_each_vfq(vf, j) {
                        struct bnx2x_vf_queue *rxq = vfq_get(vf, j);
 
@@ -1920,11 +1927,12 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)
                                cpu_to_le32(U64_HI(q_stats_addr));
                        cur_query_entry->address.lo =
                                cpu_to_le32(U64_LO(q_stats_addr));
-                       DP(BNX2X_MSG_IOV,
-                          "added address %x %x for vf %d queue %d client %d\n",
-                          cur_query_entry->address.hi,
-                          cur_query_entry->address.lo, cur_query_entry->funcID,
-                          j, cur_query_entry->index);
+                       DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
+                              "added address %x %x for vf %d queue %d client %d\n",
+                              cur_query_entry->address.hi,
+                              cur_query_entry->address.lo,
+                              cur_query_entry->funcID,
+                              j, cur_query_entry->index);
                        cur_query_entry++;
                        cur_data_offset += sizeof(struct per_queue_stats);
                        stats_count++;
index 7a6d406f4c111774ea606c98253608273ae8787b..888d0b6632e86f2f7ab7e2f9e605be87fa4c7061 100644 (file)
@@ -114,6 +114,7 @@ struct bnx2x_vf_mac_vlan_filter {
        (BNX2X_VF_FILTER_MAC | BNX2X_VF_FILTER_VLAN) /*shortcut*/
 
        bool add;
+       bool applied;
        u8 *mac;
        u16 vid;
 };
index bfae300cf25ff881292dc36ad56e51e37132cd76..76a4668c50fe98edb3d6e955351a357a3e3f0608 100644 (file)
@@ -868,7 +868,7 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev)
        struct bnx2x *bp = netdev_priv(dev);
        struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters;
        struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
-       int rc, i = 0;
+       int rc = 0, i = 0;
        struct netdev_hw_addr *ha;
 
        if (bp->state != BNX2X_STATE_OPEN) {
@@ -883,6 +883,15 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev)
        /* Get Rx mode requested */
        DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags);
 
+       /* We support PFVF_MAX_MULTICAST_PER_VF mcast addresses tops */
+       if (netdev_mc_count(dev) > PFVF_MAX_MULTICAST_PER_VF) {
+               DP(NETIF_MSG_IFUP,
+                  "VF supports not more than %d multicast MAC addresses\n",
+                  PFVF_MAX_MULTICAST_PER_VF);
+               rc = -EINVAL;
+               goto out;
+       }
+
        netdev_for_each_mc_addr(ha, dev) {
                DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
                   bnx2x_mc_addr(ha));
@@ -890,16 +899,6 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev)
                i++;
        }
 
-       /* We support four PFVF_MAX_MULTICAST_PER_VF mcast
-         * addresses tops
-         */
-       if (i >= PFVF_MAX_MULTICAST_PER_VF) {
-               DP(NETIF_MSG_IFUP,
-                  "VF supports not more than %d multicast MAC addresses\n",
-                  PFVF_MAX_MULTICAST_PER_VF);
-               return -EINVAL;
-       }
-
        req->n_multicast = i;
        req->flags |= VFPF_SET_Q_FILTERS_MULTICAST_CHANGED;
        req->vf_qid = 0;
@@ -924,7 +923,7 @@ int bnx2x_vfpf_set_mcast(struct net_device *dev)
 out:
        bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
-       return 0;
+       return rc;
 }
 
 /* request pf to add a vlan for the vf */
@@ -1778,6 +1777,23 @@ static int bnx2x_vf_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                goto op_err;
                }
 
+               /* build vlan list */
+               fl = NULL;
+
+               rc = bnx2x_vf_mbx_macvlan_list(bp, vf, msg, &fl,
+                                              VFPF_VLAN_FILTER);
+               if (rc)
+                       goto op_err;
+
+               if (fl) {
+                       /* set vlan list */
+                       rc = bnx2x_vf_mac_vlan_config_list(bp, vf, fl,
+                                                          msg->vf_qid,
+                                                          false);
+                       if (rc)
+                               goto op_err;
+               }
+
        }
 
        if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
index 235733e91c791b8ff04951cbdd42ec10ab435bae..32de4589d16a2cde27f2e5674b234e2b7185f00d 100644 (file)
@@ -4465,6 +4465,10 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
                vf->vlan = le16_to_cpu(resp->vlan) & VLAN_VID_MASK;
        }
 #endif
+       if (BNXT_PF(bp) && (le16_to_cpu(resp->flags) &
+                           FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED))
+               bp->flags |= BNXT_FLAG_FW_LLDP_AGENT;
+
        switch (resp->port_partition_type) {
        case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0:
        case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5:
@@ -5507,8 +5511,9 @@ static int bnxt_hwrm_phy_qcaps(struct bnxt *bp)
                bp->lpi_tmr_hi = le32_to_cpu(resp->valid_tx_lpi_timer_high) &
                                 PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_HIGH_MASK;
        }
-       link_info->support_auto_speeds =
-               le16_to_cpu(resp->supported_speeds_auto_mode);
+       if (resp->supported_speeds_auto_mode)
+               link_info->support_auto_speeds =
+                       le16_to_cpu(resp->supported_speeds_auto_mode);
 
 hwrm_phy_qcaps_exit:
        mutex_unlock(&bp->hwrm_cmd_lock);
@@ -6495,8 +6500,14 @@ static void bnxt_reset_task(struct bnxt *bp, bool silent)
        if (!silent)
                bnxt_dbg_dump_states(bp);
        if (netif_running(bp->dev)) {
+               int rc;
+
+               if (!silent)
+                       bnxt_ulp_stop(bp);
                bnxt_close_nic(bp, false, false);
-               bnxt_open_nic(bp, false, false);
+               rc = bnxt_open_nic(bp, false, false);
+               if (!silent && !rc)
+                       bnxt_ulp_start(bp);
        }
 }
 
@@ -7444,6 +7455,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto init_err_pci_clean;
 
+       rc = bnxt_hwrm_func_reset(bp);
+       if (rc)
+               goto init_err_pci_clean;
+
        bnxt_hwrm_fw_set_time(bp);
 
        dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
@@ -7554,10 +7569,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto init_err_pci_clean;
 
-       rc = bnxt_hwrm_func_reset(bp);
-       if (rc)
-               goto init_err_pci_clean;
-
        rc = bnxt_init_int_mode(bp);
        if (rc)
                goto init_err_pci_clean;
index faf26a2f726b808792fd837437bf7abb9279a8c7..c7a5b84a5cb20ecb1112f831d868238f9cead76b 100644 (file)
@@ -993,6 +993,7 @@ struct bnxt {
                                         BNXT_FLAG_ROCEV2_CAP)
        #define BNXT_FLAG_NO_AGG_RINGS  0x20000
        #define BNXT_FLAG_RX_PAGE_MODE  0x40000
+       #define BNXT_FLAG_FW_LLDP_AGENT 0x80000
        #define BNXT_FLAG_CHIP_NITRO_A0 0x1000000
 
        #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA |             \
index fdf2d8caf7bfaae56b4b39c415feaa343f29d579..03532061d211b168d1bd7774d2aeea9b4ed3a776 100644 (file)
@@ -474,7 +474,7 @@ void bnxt_dcb_init(struct bnxt *bp)
                return;
 
        bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
-       if (BNXT_PF(bp))
+       if (BNXT_PF(bp) && !(bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
                bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
        else
                bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
index f92896835d2a4ceb18e7d69fdc53ce7730402667..365895ed3c3e240584da21fad2caebc6384482d5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Broadcom GENET (Gigabit Ethernet) controller driver
  *
- * Copyright (c) 2014 Broadcom Corporation
+ * Copyright (c) 2014-2017 Broadcom
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -450,6 +450,22 @@ static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
                        genet_dma_ring_regs[r]);
 }
 
+static int bcmgenet_begin(struct net_device *dev)
+{
+       struct bcmgenet_priv *priv = netdev_priv(dev);
+
+       /* Turn on the clock */
+       return clk_prepare_enable(priv->clk);
+}
+
+static void bcmgenet_complete(struct net_device *dev)
+{
+       struct bcmgenet_priv *priv = netdev_priv(dev);
+
+       /* Turn off the clock */
+       clk_disable_unprepare(priv->clk);
+}
+
 static int bcmgenet_get_link_ksettings(struct net_device *dev,
                                       struct ethtool_link_ksettings *cmd)
 {
@@ -778,8 +794,9 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
        STAT_GENET_RUNT("rx_runt_bytes", mib.rx_runt_bytes),
        /* Misc UniMAC counters */
        STAT_GENET_MISC("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt,
-                       UMAC_RBUF_OVFL_CNT),
-       STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT),
+                       UMAC_RBUF_OVFL_CNT_V1),
+       STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt,
+                       UMAC_RBUF_ERR_CNT_V1),
        STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT),
        STAT_GENET_SOFT_MIB("alloc_rx_buff_failed", mib.alloc_rx_buff_failed),
        STAT_GENET_SOFT_MIB("rx_dma_failed", mib.rx_dma_failed),
@@ -821,6 +838,45 @@ static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,
        }
 }
 
+static u32 bcmgenet_update_stat_misc(struct bcmgenet_priv *priv, u16 offset)
+{
+       u16 new_offset;
+       u32 val;
+
+       switch (offset) {
+       case UMAC_RBUF_OVFL_CNT_V1:
+               if (GENET_IS_V2(priv))
+                       new_offset = RBUF_OVFL_CNT_V2;
+               else
+                       new_offset = RBUF_OVFL_CNT_V3PLUS;
+
+               val = bcmgenet_rbuf_readl(priv, new_offset);
+               /* clear if overflowed */
+               if (val == ~0)
+                       bcmgenet_rbuf_writel(priv, 0, new_offset);
+               break;
+       case UMAC_RBUF_ERR_CNT_V1:
+               if (GENET_IS_V2(priv))
+                       new_offset = RBUF_ERR_CNT_V2;
+               else
+                       new_offset = RBUF_ERR_CNT_V3PLUS;
+
+               val = bcmgenet_rbuf_readl(priv, new_offset);
+               /* clear if overflowed */
+               if (val == ~0)
+                       bcmgenet_rbuf_writel(priv, 0, new_offset);
+               break;
+       default:
+               val = bcmgenet_umac_readl(priv, offset);
+               /* clear if overflowed */
+               if (val == ~0)
+                       bcmgenet_umac_writel(priv, 0, offset);
+               break;
+       }
+
+       return val;
+}
+
 static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
 {
        int i, j = 0;
@@ -836,19 +892,28 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
                case BCMGENET_STAT_NETDEV:
                case BCMGENET_STAT_SOFT:
                        continue;
-               case BCMGENET_STAT_MIB_RX:
-               case BCMGENET_STAT_MIB_TX:
                case BCMGENET_STAT_RUNT:
-                       if (s->type != BCMGENET_STAT_MIB_RX)
-                               offset = BCMGENET_STAT_OFFSET;
+                       offset += BCMGENET_STAT_OFFSET;
+                       /* fall through */
+               case BCMGENET_STAT_MIB_TX:
+                       offset += BCMGENET_STAT_OFFSET;
+                       /* fall through */
+               case BCMGENET_STAT_MIB_RX:
                        val = bcmgenet_umac_readl(priv,
                                                  UMAC_MIB_START + j + offset);
+                       offset = 0;     /* Reset Offset */
                        break;
                case BCMGENET_STAT_MISC:
-                       val = bcmgenet_umac_readl(priv, s->reg_offset);
-                       /* clear if overflowed */
-                       if (val == ~0)
-                               bcmgenet_umac_writel(priv, 0, s->reg_offset);
+                       if (GENET_IS_V1(priv)) {
+                               val = bcmgenet_umac_readl(priv, s->reg_offset);
+                               /* clear if overflowed */
+                               if (val == ~0)
+                                       bcmgenet_umac_writel(priv, 0,
+                                                            s->reg_offset);
+                       } else {
+                               val = bcmgenet_update_stat_misc(priv,
+                                                               s->reg_offset);
+                       }
                        break;
                }
 
@@ -973,6 +1038,8 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
 
 /* standard ethtool support functions. */
 static const struct ethtool_ops bcmgenet_ethtool_ops = {
+       .begin                  = bcmgenet_begin,
+       .complete               = bcmgenet_complete,
        .get_strings            = bcmgenet_get_strings,
        .get_sset_count         = bcmgenet_get_sset_count,
        .get_ethtool_stats      = bcmgenet_get_ethtool_stats,
@@ -1167,7 +1234,6 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
        struct bcmgenet_priv *priv = netdev_priv(dev);
        struct device *kdev = &priv->pdev->dev;
        struct enet_cb *tx_cb_ptr;
-       struct netdev_queue *txq;
        unsigned int pkts_compl = 0;
        unsigned int bytes_compl = 0;
        unsigned int c_index;
@@ -1219,13 +1285,8 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
        dev->stats.tx_packets += pkts_compl;
        dev->stats.tx_bytes += bytes_compl;
 
-       txq = netdev_get_tx_queue(dev, ring->queue);
-       netdev_tx_completed_queue(txq, pkts_compl, bytes_compl);
-
-       if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
-               if (netif_tx_queue_stopped(txq))
-                       netif_tx_wake_queue(txq);
-       }
+       netdev_tx_completed_queue(netdev_get_tx_queue(dev, ring->queue),
+                                 pkts_compl, bytes_compl);
 
        return pkts_compl;
 }
@@ -1248,8 +1309,16 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
        struct bcmgenet_tx_ring *ring =
                container_of(napi, struct bcmgenet_tx_ring, napi);
        unsigned int work_done = 0;
+       struct netdev_queue *txq;
+       unsigned long flags;
 
-       work_done = bcmgenet_tx_reclaim(ring->priv->dev, ring);
+       spin_lock_irqsave(&ring->lock, flags);
+       work_done = __bcmgenet_tx_reclaim(ring->priv->dev, ring);
+       if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
+               txq = netdev_get_tx_queue(ring->priv->dev, ring->queue);
+               netif_tx_wake_queue(txq);
+       }
+       spin_unlock_irqrestore(&ring->lock, flags);
 
        if (work_done == 0) {
                napi_complete(napi);
@@ -2457,24 +2526,28 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
 /* Interrupt bottom half */
 static void bcmgenet_irq_task(struct work_struct *work)
 {
+       unsigned long flags;
+       unsigned int status;
        struct bcmgenet_priv *priv = container_of(
                        work, struct bcmgenet_priv, bcmgenet_irq_work);
 
        netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
 
-       if (priv->irq0_stat & UMAC_IRQ_MPD_R) {
-               priv->irq0_stat &= ~UMAC_IRQ_MPD_R;
+       spin_lock_irqsave(&priv->lock, flags);
+       status = priv->irq0_stat;
+       priv->irq0_stat = 0;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (status & UMAC_IRQ_MPD_R) {
                netif_dbg(priv, wol, priv->dev,
                          "magic packet detected, waking up\n");
                bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
        }
 
        /* Link UP/DOWN event */
-       if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) {
+       if (status & UMAC_IRQ_LINK_EVENT)
                phy_mac_interrupt(priv->phydev,
-                                 !!(priv->irq0_stat & UMAC_IRQ_LINK_UP));
-               priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT;
-       }
+                                 !!(status & UMAC_IRQ_LINK_UP));
 }
 
 /* bcmgenet_isr1: handle Rx and Tx priority queues */
@@ -2483,22 +2556,21 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
        struct bcmgenet_priv *priv = dev_id;
        struct bcmgenet_rx_ring *rx_ring;
        struct bcmgenet_tx_ring *tx_ring;
-       unsigned int index;
+       unsigned int index, status;
 
-       /* Save irq status for bottom-half processing. */
-       priv->irq1_stat =
-               bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
+       /* Read irq status */
+       status = bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
                ~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS);
 
        /* clear interrupts */
-       bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
+       bcmgenet_intrl2_1_writel(priv, status, INTRL2_CPU_CLEAR);
 
        netif_dbg(priv, intr, priv->dev,
-                 "%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
+                 "%s: IRQ=0x%x\n", __func__, status);
 
        /* Check Rx priority queue interrupts */
        for (index = 0; index < priv->hw_params->rx_queues; index++) {
-               if (!(priv->irq1_stat & BIT(UMAC_IRQ1_RX_INTR_SHIFT + index)))
+               if (!(status & BIT(UMAC_IRQ1_RX_INTR_SHIFT + index)))
                        continue;
 
                rx_ring = &priv->rx_rings[index];
@@ -2511,7 +2583,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
 
        /* Check Tx priority queue interrupts */
        for (index = 0; index < priv->hw_params->tx_queues; index++) {
-               if (!(priv->irq1_stat & BIT(index)))
+               if (!(status & BIT(index)))
                        continue;
 
                tx_ring = &priv->tx_rings[index];
@@ -2531,19 +2603,20 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
        struct bcmgenet_priv *priv = dev_id;
        struct bcmgenet_rx_ring *rx_ring;
        struct bcmgenet_tx_ring *tx_ring;
+       unsigned int status;
+       unsigned long flags;
 
-       /* Save irq status for bottom-half processing. */
-       priv->irq0_stat =
-               bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
+       /* Read irq status */
+       status = bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
                ~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
 
        /* clear interrupts */
-       bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
+       bcmgenet_intrl2_0_writel(priv, status, INTRL2_CPU_CLEAR);
 
        netif_dbg(priv, intr, priv->dev,
-                 "IRQ=0x%x\n", priv->irq0_stat);
+                 "IRQ=0x%x\n", status);
 
-       if (priv->irq0_stat & UMAC_IRQ_RXDMA_DONE) {
+       if (status & UMAC_IRQ_RXDMA_DONE) {
                rx_ring = &priv->rx_rings[DESC_INDEX];
 
                if (likely(napi_schedule_prep(&rx_ring->napi))) {
@@ -2552,7 +2625,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
                }
        }
 
-       if (priv->irq0_stat & UMAC_IRQ_TXDMA_DONE) {
+       if (status & UMAC_IRQ_TXDMA_DONE) {
                tx_ring = &priv->tx_rings[DESC_INDEX];
 
                if (likely(napi_schedule_prep(&tx_ring->napi))) {
@@ -2561,22 +2634,23 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
                }
        }
 
-       if (priv->irq0_stat & (UMAC_IRQ_PHY_DET_R |
-                               UMAC_IRQ_PHY_DET_F |
-                               UMAC_IRQ_LINK_EVENT |
-                               UMAC_IRQ_HFB_SM |
-                               UMAC_IRQ_HFB_MM |
-                               UMAC_IRQ_MPD_R)) {
-               /* all other interested interrupts handled in bottom half */
-               schedule_work(&priv->bcmgenet_irq_work);
-       }
-
        if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
-           priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
-               priv->irq0_stat &= ~(UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
+               status & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
                wake_up(&priv->wq);
        }
 
+       /* all other interested interrupts handled in bottom half */
+       status &= (UMAC_IRQ_LINK_EVENT |
+                  UMAC_IRQ_MPD_R);
+       if (status) {
+               /* Save irq status for bottom-half processing. */
+               spin_lock_irqsave(&priv->lock, flags);
+               priv->irq0_stat |= status;
+               spin_unlock_irqrestore(&priv->lock, flags);
+
+               schedule_work(&priv->bcmgenet_irq_work);
+       }
+
        return IRQ_HANDLED;
 }
 
@@ -2801,6 +2875,8 @@ err_irq0:
 err_fini_dma:
        bcmgenet_fini_dma(priv);
 err_clk_disable:
+       if (priv->internal_phy)
+               bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
        clk_disable_unprepare(priv->clk);
        return ret;
 }
@@ -3177,6 +3253,12 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
         */
        gphy_rev = reg & 0xffff;
 
+       /* This is reserved so should require special treatment */
+       if (gphy_rev == 0 || gphy_rev == 0x01ff) {
+               pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev);
+               return;
+       }
+
        /* This is the good old scheme, just GPHY major, no minor nor patch */
        if ((gphy_rev & 0xf0) != 0)
                priv->gphy_rev = gphy_rev << 8;
@@ -3185,12 +3267,6 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
        else if ((gphy_rev & 0xff00) != 0)
                priv->gphy_rev = gphy_rev;
 
-       /* This is reserved so should require special treatment */
-       else if (gphy_rev == 0 || gphy_rev == 0x01ff) {
-               pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev);
-               return;
-       }
-
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
        if (!(params->flags & GENET_HAS_40BITS))
                pr_warn("GENET does not support 40-bits PA\n");
@@ -3233,6 +3309,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
        const void *macaddr;
        struct resource *r;
        int err = -EIO;
+       const char *phy_mode_str;
 
        /* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */
        dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,
@@ -3276,6 +3353,8 @@ static int bcmgenet_probe(struct platform_device *pdev)
                goto err;
        }
 
+       spin_lock_init(&priv->lock);
+
        SET_NETDEV_DEV(dev, &pdev->dev);
        dev_set_drvdata(&pdev->dev, dev);
        ether_addr_copy(dev->dev_addr, macaddr);
@@ -3338,6 +3417,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
                priv->clk_eee = NULL;
        }
 
+       /* If this is an internal GPHY, power it on now, before UniMAC is
+        * brought out of reset as absolutely no UniMAC activity is allowed
+        */
+       if (dn && !of_property_read_string(dn, "phy-mode", &phy_mode_str) &&
+           !strcasecmp(phy_mode_str, "internal"))
+               bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
+
        err = reset_umac(priv);
        if (err)
                goto err_clk_disable;
@@ -3395,7 +3481,8 @@ static int bcmgenet_suspend(struct device *d)
 
        bcmgenet_netif_stop(dev);
 
-       phy_suspend(priv->phydev);
+       if (!device_may_wakeup(d))
+               phy_suspend(priv->phydev);
 
        netif_device_detach(dev);
 
@@ -3492,7 +3579,8 @@ static int bcmgenet_resume(struct device *d)
 
        netif_device_attach(dev);
 
-       phy_resume(priv->phydev);
+       if (!device_may_wakeup(d))
+               phy_resume(priv->phydev);
 
        if (priv->eee.eee_enabled)
                bcmgenet_eee_enable_set(dev, true);
@@ -3502,6 +3590,8 @@ static int bcmgenet_resume(struct device *d)
        return 0;
 
 out_clk_disable:
+       if (priv->internal_phy)
+               bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
        clk_disable_unprepare(priv->clk);
        return ret;
 }
index 1e2dc34d331a49e05a8fc9a66156dfeeb00ee10f..db7f289d65ae2abd1589446ee0cadc00ffbf0254 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Broadcom Corporation
+ * Copyright (c) 2014-2017 Broadcom
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -214,7 +214,9 @@ struct bcmgenet_mib_counters {
 #define  MDIO_REG_SHIFT                        16
 #define  MDIO_REG_MASK                 0x1F
 
-#define UMAC_RBUF_OVFL_CNT             0x61C
+#define UMAC_RBUF_OVFL_CNT_V1          0x61C
+#define RBUF_OVFL_CNT_V2               0x80
+#define RBUF_OVFL_CNT_V3PLUS           0x94
 
 #define UMAC_MPD_CTRL                  0x620
 #define  MPD_EN                                (1 << 0)
@@ -224,7 +226,9 @@ struct bcmgenet_mib_counters {
 
 #define UMAC_MPD_PW_MS                 0x624
 #define UMAC_MPD_PW_LS                 0x628
-#define UMAC_RBUF_ERR_CNT              0x634
+#define UMAC_RBUF_ERR_CNT_V1           0x634
+#define RBUF_ERR_CNT_V2                        0x84
+#define RBUF_ERR_CNT_V3PLUS            0x98
 #define UMAC_MDF_ERR_CNT               0x638
 #define UMAC_MDF_CTRL                  0x650
 #define UMAC_MDF_ADDR                  0x654
@@ -619,11 +623,13 @@ struct bcmgenet_priv {
        struct work_struct bcmgenet_irq_work;
        int irq0;
        int irq1;
-       unsigned int irq0_stat;
-       unsigned int irq1_stat;
        int wol_irq;
        bool wol_irq_disabled;
 
+       /* shared status */
+       spinlock_t lock;
+       unsigned int irq0_stat;
+
        /* HW descriptors/checksum variables */
        bool desc_64b_en;
        bool desc_rxchk_en;
index e87607621e62a076104d67046a10603305d66ecf..2f9281936f0e434a328e1c716a29a76be2d9090c 100644 (file)
@@ -220,20 +220,6 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
        udelay(60);
 }
 
-static void bcmgenet_internal_phy_setup(struct net_device *dev)
-{
-       struct bcmgenet_priv *priv = netdev_priv(dev);
-       u32 reg;
-
-       /* Power up PHY */
-       bcmgenet_phy_power_set(dev, true);
-       /* enable APD */
-       reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
-       reg |= EXT_PWR_DN_EN_LD;
-       bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
-       bcmgenet_mii_reset(dev);
-}
-
 static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
 {
        u32 reg;
@@ -281,7 +267,6 @@ int bcmgenet_mii_config(struct net_device *dev)
 
                if (priv->internal_phy) {
                        phy_name = "internal PHY";
-                       bcmgenet_internal_phy_setup(dev);
                } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
                        phy_name = "MoCA";
                        bcmgenet_moca_phy_setup(priv);
index 05c1c1dd7751bd720fac026876c7fcf7392eca03..cebfe3bd086e36f60f717579f03037058b1d1d9e 100644 (file)
@@ -325,7 +325,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
                return PTR_ERR(kern_buf);
 
        rc = sscanf(kern_buf, "%x:%x", &addr, &len);
-       if (rc < 2) {
+       if (rc < 2 || len > UINT_MAX >> 2) {
                netdev_warn(bnad->netdev, "failed to read user buffer\n");
                kfree(kern_buf);
                return -EINVAL;
index be9c0e3f5ade7d4e61694da214702f0223ab5d59..92f46b1375c32527b29e24a4476d6b455835bd46 100644 (file)
@@ -152,7 +152,7 @@ struct octnic_gather {
         */
        struct octeon_sg_entry *sg;
 
-       u64 sg_dma_ptr;
+       dma_addr_t sg_dma_ptr;
 };
 
 struct handshake {
@@ -734,6 +734,9 @@ static void delete_glists(struct lio *lio)
        struct octnic_gather *g;
        int i;
 
+       kfree(lio->glist_lock);
+       lio->glist_lock = NULL;
+
        if (!lio->glist)
                return;
 
@@ -741,23 +744,26 @@ static void delete_glists(struct lio *lio)
                do {
                        g = (struct octnic_gather *)
                                list_delete_head(&lio->glist[i]);
-                       if (g) {
-                               if (g->sg) {
-                                       dma_unmap_single(&lio->oct_dev->
-                                                        pci_dev->dev,
-                                                        g->sg_dma_ptr,
-                                                        g->sg_size,
-                                                        DMA_TO_DEVICE);
-                                       kfree((void *)((unsigned long)g->sg -
-                                                      g->adjust));
-                               }
+                       if (g)
                                kfree(g);
-                       }
                } while (g);
+
+               if (lio->glists_virt_base && lio->glists_virt_base[i]) {
+                       lio_dma_free(lio->oct_dev,
+                                    lio->glist_entry_size * lio->tx_qsize,
+                                    lio->glists_virt_base[i],
+                                    lio->glists_dma_base[i]);
+               }
        }
 
-       kfree((void *)lio->glist);
-       kfree((void *)lio->glist_lock);
+       kfree(lio->glists_virt_base);
+       lio->glists_virt_base = NULL;
+
+       kfree(lio->glists_dma_base);
+       lio->glists_dma_base = NULL;
+
+       kfree(lio->glist);
+       lio->glist = NULL;
 }
 
 /**
@@ -772,13 +778,30 @@ static int setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs)
        lio->glist_lock = kcalloc(num_iqs, sizeof(*lio->glist_lock),
                                  GFP_KERNEL);
        if (!lio->glist_lock)
-               return 1;
+               return -ENOMEM;
 
        lio->glist = kcalloc(num_iqs, sizeof(*lio->glist),
                             GFP_KERNEL);
        if (!lio->glist) {
-               kfree((void *)lio->glist_lock);
-               return 1;
+               kfree(lio->glist_lock);
+               lio->glist_lock = NULL;
+               return -ENOMEM;
+       }
+
+       lio->glist_entry_size =
+               ROUNDUP8((ROUNDUP4(OCTNIC_MAX_SG) >> 2) * OCT_SG_ENTRY_SIZE);
+
+       /* allocate memory to store virtual and dma base address of
+        * per glist consistent memory
+        */
+       lio->glists_virt_base = kcalloc(num_iqs, sizeof(*lio->glists_virt_base),
+                                       GFP_KERNEL);
+       lio->glists_dma_base = kcalloc(num_iqs, sizeof(*lio->glists_dma_base),
+                                      GFP_KERNEL);
+
+       if (!lio->glists_virt_base || !lio->glists_dma_base) {
+               delete_glists(lio);
+               return -ENOMEM;
        }
 
        for (i = 0; i < num_iqs; i++) {
@@ -788,6 +811,16 @@ static int setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs)
 
                INIT_LIST_HEAD(&lio->glist[i]);
 
+               lio->glists_virt_base[i] =
+                       lio_dma_alloc(oct,
+                                     lio->glist_entry_size * lio->tx_qsize,
+                                     &lio->glists_dma_base[i]);
+
+               if (!lio->glists_virt_base[i]) {
+                       delete_glists(lio);
+                       return -ENOMEM;
+               }
+
                for (j = 0; j < lio->tx_qsize; j++) {
                        g = kzalloc_node(sizeof(*g), GFP_KERNEL,
                                         numa_node);
@@ -796,43 +829,18 @@ static int setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs)
                        if (!g)
                                break;
 
-                       g->sg_size = ((ROUNDUP4(OCTNIC_MAX_SG) >> 2) *
-                                     OCT_SG_ENTRY_SIZE);
+                       g->sg = lio->glists_virt_base[i] +
+                               (j * lio->glist_entry_size);
 
-                       g->sg = kmalloc_node(g->sg_size + 8,
-                                            GFP_KERNEL, numa_node);
-                       if (!g->sg)
-                               g->sg = kmalloc(g->sg_size + 8, GFP_KERNEL);
-                       if (!g->sg) {
-                               kfree(g);
-                               break;
-                       }
-
-                       /* The gather component should be aligned on 64-bit
-                        * boundary
-                        */
-                       if (((unsigned long)g->sg) & 7) {
-                               g->adjust = 8 - (((unsigned long)g->sg) & 7);
-                               g->sg = (struct octeon_sg_entry *)
-                                       ((unsigned long)g->sg + g->adjust);
-                       }
-                       g->sg_dma_ptr = dma_map_single(&oct->pci_dev->dev,
-                                                      g->sg, g->sg_size,
-                                                      DMA_TO_DEVICE);
-                       if (dma_mapping_error(&oct->pci_dev->dev,
-                                             g->sg_dma_ptr)) {
-                               kfree((void *)((unsigned long)g->sg -
-                                              g->adjust));
-                               kfree(g);
-                               break;
-                       }
+                       g->sg_dma_ptr = lio->glists_dma_base[i] +
+                                       (j * lio->glist_entry_size);
 
                        list_add_tail(&g->list, &lio->glist[i]);
                }
 
                if (j != lio->tx_qsize) {
                        delete_glists(lio);
-                       return 1;
+                       return -ENOMEM;
                }
        }
 
@@ -1885,9 +1893,6 @@ static void free_netsgbuf(void *buf)
                i++;
        }
 
-       dma_sync_single_for_cpu(&lio->oct_dev->pci_dev->dev,
-                               g->sg_dma_ptr, g->sg_size, DMA_TO_DEVICE);
-
        iq = skb_iq(lio, skb);
        spin_lock(&lio->glist_lock[iq]);
        list_add_tail(&g->list, &lio->glist[iq]);
@@ -1933,9 +1938,6 @@ static void free_netsgbuf_with_resp(void *buf)
                i++;
        }
 
-       dma_sync_single_for_cpu(&lio->oct_dev->pci_dev->dev,
-                               g->sg_dma_ptr, g->sg_size, DMA_TO_DEVICE);
-
        iq = skb_iq(lio, skb);
 
        spin_lock(&lio->glist_lock[iq]);
@@ -3273,8 +3275,6 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
                        i++;
                }
 
-               dma_sync_single_for_device(&oct->pci_dev->dev, g->sg_dma_ptr,
-                                          g->sg_size, DMA_TO_DEVICE);
                dptr = g->sg_dma_ptr;
 
                if (OCTEON_CN23XX_PF(oct))
index 9d5e03502c76cbfe3c8372a5d3e73c67e07e3a03..7b83be4ce1fe0ce5cab0c7ff889edbf334a5a065 100644 (file)
@@ -108,6 +108,8 @@ struct octnic_gather {
         * received from the IP layer.
         */
        struct octeon_sg_entry *sg;
+
+       dma_addr_t sg_dma_ptr;
 };
 
 struct octeon_device_priv {
@@ -490,6 +492,9 @@ static void delete_glists(struct lio *lio)
        struct octnic_gather *g;
        int i;
 
+       kfree(lio->glist_lock);
+       lio->glist_lock = NULL;
+
        if (!lio->glist)
                return;
 
@@ -497,17 +502,26 @@ static void delete_glists(struct lio *lio)
                do {
                        g = (struct octnic_gather *)
                            list_delete_head(&lio->glist[i]);
-                       if (g) {
-                               if (g->sg)
-                                       kfree((void *)((unsigned long)g->sg -
-                                                       g->adjust));
+                       if (g)
                                kfree(g);
-                       }
                } while (g);
+
+               if (lio->glists_virt_base && lio->glists_virt_base[i]) {
+                       lio_dma_free(lio->oct_dev,
+                                    lio->glist_entry_size * lio->tx_qsize,
+                                    lio->glists_virt_base[i],
+                                    lio->glists_dma_base[i]);
+               }
        }
 
+       kfree(lio->glists_virt_base);
+       lio->glists_virt_base = NULL;
+
+       kfree(lio->glists_dma_base);
+       lio->glists_dma_base = NULL;
+
        kfree(lio->glist);
-       kfree(lio->glist_lock);
+       lio->glist = NULL;
 }
 
 /**
@@ -522,13 +536,30 @@ static int setup_glists(struct lio *lio, int num_iqs)
        lio->glist_lock =
            kzalloc(sizeof(*lio->glist_lock) * num_iqs, GFP_KERNEL);
        if (!lio->glist_lock)
-               return 1;
+               return -ENOMEM;
 
        lio->glist =
            kzalloc(sizeof(*lio->glist) * num_iqs, GFP_KERNEL);
        if (!lio->glist) {
                kfree(lio->glist_lock);
-               return 1;
+               lio->glist_lock = NULL;
+               return -ENOMEM;
+       }
+
+       lio->glist_entry_size =
+               ROUNDUP8((ROUNDUP4(OCTNIC_MAX_SG) >> 2) * OCT_SG_ENTRY_SIZE);
+
+       /* allocate memory to store virtual and dma base address of
+        * per glist consistent memory
+        */
+       lio->glists_virt_base = kcalloc(num_iqs, sizeof(*lio->glists_virt_base),
+                                       GFP_KERNEL);
+       lio->glists_dma_base = kcalloc(num_iqs, sizeof(*lio->glists_dma_base),
+                                      GFP_KERNEL);
+
+       if (!lio->glists_virt_base || !lio->glists_dma_base) {
+               delete_glists(lio);
+               return -ENOMEM;
        }
 
        for (i = 0; i < num_iqs; i++) {
@@ -536,34 +567,33 @@ static int setup_glists(struct lio *lio, int num_iqs)
 
                INIT_LIST_HEAD(&lio->glist[i]);
 
+               lio->glists_virt_base[i] =
+                       lio_dma_alloc(lio->oct_dev,
+                                     lio->glist_entry_size * lio->tx_qsize,
+                                     &lio->glists_dma_base[i]);
+
+               if (!lio->glists_virt_base[i]) {
+                       delete_glists(lio);
+                       return -ENOMEM;
+               }
+
                for (j = 0; j < lio->tx_qsize; j++) {
                        g = kzalloc(sizeof(*g), GFP_KERNEL);
                        if (!g)
                                break;
 
-                       g->sg_size = ((ROUNDUP4(OCTNIC_MAX_SG) >> 2) *
-                                     OCT_SG_ENTRY_SIZE);
+                       g->sg = lio->glists_virt_base[i] +
+                               (j * lio->glist_entry_size);
 
-                       g->sg = kmalloc(g->sg_size + 8, GFP_KERNEL);
-                       if (!g->sg) {
-                               kfree(g);
-                               break;
-                       }
+                       g->sg_dma_ptr = lio->glists_dma_base[i] +
+                                       (j * lio->glist_entry_size);
 
-                       /* The gather component should be aligned on 64-bit
-                        * boundary
-                        */
-                       if (((unsigned long)g->sg) & 7) {
-                               g->adjust = 8 - (((unsigned long)g->sg) & 7);
-                               g->sg = (struct octeon_sg_entry *)
-                                       ((unsigned long)g->sg + g->adjust);
-                       }
                        list_add_tail(&g->list, &lio->glist[i]);
                }
 
                if (j != lio->tx_qsize) {
                        delete_glists(lio);
-                       return 1;
+                       return -ENOMEM;
                }
        }
 
@@ -1324,10 +1354,6 @@ static void free_netsgbuf(void *buf)
                i++;
        }
 
-       dma_unmap_single(&lio->oct_dev->pci_dev->dev,
-                        finfo->dptr, g->sg_size,
-                        DMA_TO_DEVICE);
-
        iq = skb_iq(lio, skb);
 
        spin_lock(&lio->glist_lock[iq]);
@@ -1374,10 +1400,6 @@ static void free_netsgbuf_with_resp(void *buf)
                i++;
        }
 
-       dma_unmap_single(&lio->oct_dev->pci_dev->dev,
-                        finfo->dptr, g->sg_size,
-                        DMA_TO_DEVICE);
-
        iq = skb_iq(lio, skb);
 
        spin_lock(&lio->glist_lock[iq]);
@@ -2382,23 +2404,7 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
                        i++;
                }
 
-               dptr = dma_map_single(&oct->pci_dev->dev,
-                                     g->sg, g->sg_size,
-                                     DMA_TO_DEVICE);
-               if (dma_mapping_error(&oct->pci_dev->dev, dptr)) {
-                       dev_err(&oct->pci_dev->dev, "%s DMA mapping error 4\n",
-                               __func__);
-                       dma_unmap_single(&oct->pci_dev->dev, g->sg[0].ptr[0],
-                                        skb->len - skb->data_len,
-                                        DMA_TO_DEVICE);
-                       for (j = 1; j <= frags; j++) {
-                               frag = &skb_shinfo(skb)->frags[j - 1];
-                               dma_unmap_page(&oct->pci_dev->dev,
-                                              g->sg[j >> 2].ptr[j & 3],
-                                              frag->size, DMA_TO_DEVICE);
-                       }
-                       return NETDEV_TX_BUSY;
-               }
+               dptr = g->sg_dma_ptr;
 
                ndata.cmd.cmd3.dptr = dptr;
                finfo->dptr = dptr;
index b3dc2e9651a8e205d7e6e451109f98e96065de2c..d29ebc531151f0fe85cb83826d3af9b069d75f52 100644 (file)
 #define   CN23XX_MAX_RINGS_PER_VF          8
 
 #define   CN23XX_MAX_INPUT_QUEUES      CN23XX_MAX_RINGS_PER_PF
-#define   CN23XX_MAX_IQ_DESCRIPTORS    2048
+#define   CN23XX_MAX_IQ_DESCRIPTORS    512
 #define   CN23XX_DB_MIN                 1
 #define   CN23XX_DB_MAX                 8
 #define   CN23XX_DB_TIMEOUT             1
 
 #define   CN23XX_MAX_OUTPUT_QUEUES     CN23XX_MAX_RINGS_PER_PF
-#define   CN23XX_MAX_OQ_DESCRIPTORS    2048
+#define   CN23XX_MAX_OQ_DESCRIPTORS    512
 #define   CN23XX_OQ_BUF_SIZE           1536
 #define   CN23XX_OQ_PKTSPER_INTR       128
 /*#define CAVIUM_ONLY_CN23XX_RX_PERF*/
-#define   CN23XX_OQ_REFIL_THRESHOLD    128
+#define   CN23XX_OQ_REFIL_THRESHOLD    16
 
 #define   CN23XX_OQ_INTR_PKT           64
 #define   CN23XX_OQ_INTR_TIME          100
index 0be87d119a979ea70117e13b2213987460da2a81..79f809479af6e7d865cc7c280c84232622af982e 100644 (file)
@@ -155,11 +155,6 @@ octeon_droq_destroy_ring_buffers(struct octeon_device *oct,
                        recv_buffer_destroy(droq->recv_buf_list[i].buffer,
                                            pg_info);
 
-               if (droq->desc_ring && droq->desc_ring[i].info_ptr)
-                       lio_unmap_ring_info(oct->pci_dev,
-                                           (u64)droq->
-                                           desc_ring[i].info_ptr,
-                                           OCT_DROQ_INFO_SIZE);
                droq->recv_buf_list[i].buffer = NULL;
        }
 
@@ -211,10 +206,7 @@ int octeon_delete_droq(struct octeon_device *oct, u32 q_no)
        vfree(droq->recv_buf_list);
 
        if (droq->info_base_addr)
-               cnnic_free_aligned_dma(oct->pci_dev, droq->info_list,
-                                      droq->info_alloc_size,
-                                      droq->info_base_addr,
-                                      droq->info_list_dma);
+               lio_free_info_buffer(oct, droq);
 
        if (droq->desc_ring)
                lio_dma_free(oct, (droq->max_count * OCT_DROQ_DESC_SIZE),
@@ -294,12 +286,7 @@ int octeon_init_droq(struct octeon_device *oct,
        dev_dbg(&oct->pci_dev->dev, "droq[%d]: num_desc: %d\n", q_no,
                droq->max_count);
 
-       droq->info_list =
-               cnnic_numa_alloc_aligned_dma((droq->max_count *
-                                             OCT_DROQ_INFO_SIZE),
-                                            &droq->info_alloc_size,
-                                            &droq->info_base_addr,
-                                            numa_node);
+       droq->info_list = lio_alloc_info_buffer(oct, droq);
        if (!droq->info_list) {
                dev_err(&oct->pci_dev->dev, "Cannot allocate memory for info list.\n");
                lio_dma_free(oct, (droq->max_count * OCT_DROQ_DESC_SIZE),
index e62074090681d3597f973f54fadb2133b21b2931..6982c0af5eccb7129123fcbb4ba8363bb7f9710a 100644 (file)
@@ -325,10 +325,10 @@ struct octeon_droq {
        size_t desc_ring_dma;
 
        /** Info ptr list are allocated at this virtual address. */
-       size_t info_base_addr;
+       void *info_base_addr;
 
        /** DMA mapped address of the info list */
-       size_t info_list_dma;
+       dma_addr_t info_list_dma;
 
        /** Allocated size of info list. */
        u32 info_alloc_size;
index aa36e9ae7676556e562a8bb4c9cb46aacc709890..bed9ef17bc26b4526cf3c57dcb4823cdc2586491 100644 (file)
@@ -140,48 +140,6 @@ err_release_region:
        return 1;
 }
 
-static inline void *
-cnnic_numa_alloc_aligned_dma(u32 size,
-                            u32 *alloc_size,
-                            size_t *orig_ptr,
-                            int numa_node)
-{
-       int retries = 0;
-       void *ptr = NULL;
-
-#define OCTEON_MAX_ALLOC_RETRIES     1
-       do {
-               struct page *page = NULL;
-
-               page = alloc_pages_node(numa_node,
-                                       GFP_KERNEL,
-                                       get_order(size));
-               if (!page)
-                       page = alloc_pages(GFP_KERNEL,
-                                          get_order(size));
-               ptr = (void *)page_address(page);
-               if ((unsigned long)ptr & 0x07) {
-                       __free_pages(page, get_order(size));
-                       ptr = NULL;
-                       /* Increment the size required if the first
-                        * attempt failed.
-                        */
-                       if (!retries)
-                               size += 7;
-               }
-               retries++;
-       } while ((retries <= OCTEON_MAX_ALLOC_RETRIES) && !ptr);
-
-       *alloc_size = size;
-       *orig_ptr = (unsigned long)ptr;
-       if ((unsigned long)ptr & 0x07)
-               ptr = (void *)(((unsigned long)ptr + 7) & ~(7UL));
-       return ptr;
-}
-
-#define cnnic_free_aligned_dma(pci_dev, ptr, size, orig_ptr, dma_addr) \
-               free_pages(orig_ptr, get_order(size))
-
 static inline int
 sleep_cond(wait_queue_head_t *wait_queue, int *condition)
 {
index 6bb89419006eb5635cc65c415ad6183f5296f6d3..eef2a1e8a7e3f96b26f004ec0eec93e447a5d61f 100644 (file)
@@ -62,6 +62,9 @@ struct lio {
 
        /** Array of gather component linked lists */
        struct list_head *glist;
+       void **glists_virt_base;
+       dma_addr_t *glists_dma_base;
+       u32 glist_entry_size;
 
        /** Pointer to the NIC properties for the Octeon device this network
         *  interface is associated with.
@@ -344,6 +347,29 @@ static inline void tx_buffer_free(void *buffer)
 #define lio_dma_free(oct, size, virt_addr, dma_addr) \
        dma_free_coherent(&(oct)->pci_dev->dev, size, virt_addr, dma_addr)
 
+static inline void *
+lio_alloc_info_buffer(struct octeon_device *oct,
+                     struct octeon_droq *droq)
+{
+       void *virt_ptr;
+
+       virt_ptr = lio_dma_alloc(oct, (droq->max_count * OCT_DROQ_INFO_SIZE),
+                                &droq->info_list_dma);
+       if (virt_ptr) {
+               droq->info_alloc_size = droq->max_count * OCT_DROQ_INFO_SIZE;
+               droq->info_base_addr = virt_ptr;
+       }
+
+       return virt_ptr;
+}
+
+static inline void lio_free_info_buffer(struct octeon_device *oct,
+                                       struct octeon_droq *droq)
+{
+       lio_dma_free(oct, droq->info_alloc_size, droq->info_base_addr,
+                    droq->info_list_dma);
+}
+
 static inline
 void *get_rbd(struct sk_buff *skb)
 {
@@ -359,22 +385,7 @@ void *get_rbd(struct sk_buff *skb)
 static inline u64
 lio_map_ring_info(struct octeon_droq *droq, u32 i)
 {
-       dma_addr_t dma_addr;
-       struct octeon_device *oct = droq->oct_dev;
-
-       dma_addr = dma_map_single(&oct->pci_dev->dev, &droq->info_list[i],
-                                 OCT_DROQ_INFO_SIZE, DMA_FROM_DEVICE);
-
-       WARN_ON(dma_mapping_error(&oct->pci_dev->dev, dma_addr));
-
-       return (u64)dma_addr;
-}
-
-static inline void
-lio_unmap_ring_info(struct pci_dev *pci_dev,
-                   u64 info_ptr, u32 size)
-{
-       dma_unmap_single(&pci_dev->dev, info_ptr, size, DMA_FROM_DEVICE);
+       return droq->info_list_dma + (i * sizeof(struct octeon_droq_info));
 }
 
 static inline u64
index e739c715356283553f4ace131a251bc4b30d6de2..2269ff562d9562eede1d1d02c2e66ee3dcfed89b 100644 (file)
@@ -269,6 +269,7 @@ struct nicvf {
 #define        MAX_QUEUES_PER_QSET                     8
        struct queue_set        *qs;
        struct nicvf_cq_poll    *napi[8];
+       void                    *iommu_domain;
        u8                      vf_id;
        u8                      sqs_id;
        bool                    sqs_mode;
index 6feaa24bcfd42bb9647298a0b665e6bf3b11d496..24017588f5317107142897ca77aa0668046532d5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/log2.h>
 #include <linux/prefetch.h>
 #include <linux/irq.h>
+#include <linux/iommu.h>
 
 #include "nic_reg.h"
 #include "nic.h"
@@ -525,7 +526,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
                        /* Get actual TSO descriptors and free them */
                        tso_sqe =
                         (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, hdr->rsvd2);
+                       nicvf_unmap_sndq_buffers(nic, sq, hdr->rsvd2,
+                                                tso_sqe->subdesc_cnt);
                        nicvf_put_sq_desc(sq, tso_sqe->subdesc_cnt + 1);
+               } else {
+                       nicvf_unmap_sndq_buffers(nic, sq, cqe_tx->sqe_ptr,
+                                                hdr->subdesc_cnt);
                }
                nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1);
                prefetch(skb);
@@ -576,6 +582,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
 {
        struct sk_buff *skb;
        struct nicvf *nic = netdev_priv(netdev);
+       struct nicvf *snic = nic;
        int err = 0;
        int rq_idx;
 
@@ -592,7 +599,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
        if (err && !cqe_rx->rb_cnt)
                return;
 
-       skb = nicvf_get_rcv_skb(nic, cqe_rx);
+       skb = nicvf_get_rcv_skb(snic, cqe_rx);
        if (!skb) {
                netdev_dbg(nic->netdev, "Packet not received\n");
                return;
@@ -1643,6 +1650,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!pass1_silicon(nic->pdev))
                nic->hw_tso = true;
 
+       /* Get iommu domain for iova to physical addr conversion */
+       nic->iommu_domain = iommu_get_domain_for_dev(dev);
+
        pci_read_config_word(nic->pdev, PCI_SUBSYSTEM_ID, &sdevid);
        if (sdevid == 0xA134)
                nic->t88 = true;
index ac0390be3b126e957071bde64daebdd29b536c34..f13289f0d2386d09e348b13c310346d42e20b74d 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/ip.h>
 #include <linux/etherdevice.h>
+#include <linux/iommu.h>
 #include <net/ip.h>
 #include <net/tso.h>
 
 #include "q_struct.h"
 #include "nicvf_queues.h"
 
+#define NICVF_PAGE_ORDER ((PAGE_SIZE <= 4096) ?  PAGE_ALLOC_COSTLY_ORDER : 0)
+
+static inline u64 nicvf_iova_to_phys(struct nicvf *nic, dma_addr_t dma_addr)
+{
+       /* Translation is installed only when IOMMU is present */
+       if (nic->iommu_domain)
+               return iommu_iova_to_phys(nic->iommu_domain, dma_addr);
+       return dma_addr;
+}
+
 static void nicvf_get_page(struct nicvf *nic)
 {
        if (!nic->rb_pageref || !nic->rb_page)
@@ -87,7 +98,7 @@ static void nicvf_free_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem)
 static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp,
                                         u32 buf_len, u64 **rbuf)
 {
-       int order = (PAGE_SIZE <= 4096) ?  PAGE_ALLOC_COSTLY_ORDER : 0;
+       int order = NICVF_PAGE_ORDER;
 
        /* Check if request can be accomodated in previous allocated page */
        if (nic->rb_page &&
@@ -97,22 +108,27 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp,
        }
 
        nicvf_get_page(nic);
-       nic->rb_page = NULL;
 
        /* Allocate a new page */
+       nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
+                                  order);
        if (!nic->rb_page) {
-               nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
-                                          order);
-               if (!nic->rb_page) {
-                       this_cpu_inc(nic->pnicvf->drv_stats->
-                                    rcv_buffer_alloc_failures);
-                       return -ENOMEM;
-               }
-               nic->rb_page_offset = 0;
+               this_cpu_inc(nic->pnicvf->drv_stats->rcv_buffer_alloc_failures);
+               return -ENOMEM;
        }
-
+       nic->rb_page_offset = 0;
 ret:
-       *rbuf = (u64 *)((u64)page_address(nic->rb_page) + nic->rb_page_offset);
+       /* HW will ensure data coherency, CPU sync not required */
+       *rbuf = (u64 *)((u64)dma_map_page_attrs(&nic->pdev->dev, nic->rb_page,
+                                               nic->rb_page_offset, buf_len,
+                                               DMA_FROM_DEVICE,
+                                               DMA_ATTR_SKIP_CPU_SYNC));
+       if (dma_mapping_error(&nic->pdev->dev, (dma_addr_t)*rbuf)) {
+               if (!nic->rb_page_offset)
+                       __free_pages(nic->rb_page, order);
+               nic->rb_page = NULL;
+               return -ENOMEM;
+       }
        nic->rb_page_offset += buf_len;
 
        return 0;
@@ -158,16 +174,21 @@ static int  nicvf_init_rbdr(struct nicvf *nic, struct rbdr *rbdr,
        rbdr->dma_size = buf_size;
        rbdr->enable = true;
        rbdr->thresh = RBDR_THRESH;
+       rbdr->head = 0;
+       rbdr->tail = 0;
 
        nic->rb_page = NULL;
        for (idx = 0; idx < ring_len; idx++) {
                err = nicvf_alloc_rcv_buffer(nic, GFP_KERNEL, RCV_FRAG_LEN,
                                             &rbuf);
-               if (err)
+               if (err) {
+                       /* To free already allocated and mapped ones */
+                       rbdr->tail = idx - 1;
                        return err;
+               }
 
                desc = GET_RBDR_DESC(rbdr, idx);
-               desc->buf_addr = virt_to_phys(rbuf) >> NICVF_RCV_BUF_ALIGN;
+               desc->buf_addr = (u64)rbuf >> NICVF_RCV_BUF_ALIGN;
        }
 
        nicvf_get_page(nic);
@@ -179,7 +200,7 @@ static int  nicvf_init_rbdr(struct nicvf *nic, struct rbdr *rbdr,
 static void nicvf_free_rbdr(struct nicvf *nic, struct rbdr *rbdr)
 {
        int head, tail;
-       u64 buf_addr;
+       u64 buf_addr, phys_addr;
        struct rbdr_entry_t *desc;
 
        if (!rbdr)
@@ -192,18 +213,26 @@ static void nicvf_free_rbdr(struct nicvf *nic, struct rbdr *rbdr)
        head = rbdr->head;
        tail = rbdr->tail;
 
-       /* Free SKBs */
+       /* Release page references */
        while (head != tail) {
                desc = GET_RBDR_DESC(rbdr, head);
-               buf_addr = desc->buf_addr << NICVF_RCV_BUF_ALIGN;
-               put_page(virt_to_page(phys_to_virt(buf_addr)));
+               buf_addr = ((u64)desc->buf_addr) << NICVF_RCV_BUF_ALIGN;
+               phys_addr = nicvf_iova_to_phys(nic, buf_addr);
+               dma_unmap_page_attrs(&nic->pdev->dev, buf_addr, RCV_FRAG_LEN,
+                                    DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+               if (phys_addr)
+                       put_page(virt_to_page(phys_to_virt(phys_addr)));
                head++;
                head &= (rbdr->dmem.q_len - 1);
        }
-       /* Free SKB of tail desc */
+       /* Release buffer of tail desc */
        desc = GET_RBDR_DESC(rbdr, tail);
-       buf_addr = desc->buf_addr << NICVF_RCV_BUF_ALIGN;
-       put_page(virt_to_page(phys_to_virt(buf_addr)));
+       buf_addr = ((u64)desc->buf_addr) << NICVF_RCV_BUF_ALIGN;
+       phys_addr = nicvf_iova_to_phys(nic, buf_addr);
+       dma_unmap_page_attrs(&nic->pdev->dev, buf_addr, RCV_FRAG_LEN,
+                            DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+       if (phys_addr)
+               put_page(virt_to_page(phys_to_virt(phys_addr)));
 
        /* Free RBDR ring */
        nicvf_free_q_desc_mem(nic, &rbdr->dmem);
@@ -250,7 +279,7 @@ refill:
                        break;
 
                desc = GET_RBDR_DESC(rbdr, tail);
-               desc->buf_addr = virt_to_phys(rbuf) >> NICVF_RCV_BUF_ALIGN;
+               desc->buf_addr = (u64)rbuf >> NICVF_RCV_BUF_ALIGN;
                refill_rb_cnt--;
                new_rb++;
        }
@@ -361,9 +390,29 @@ static int nicvf_init_snd_queue(struct nicvf *nic,
        return 0;
 }
 
+void nicvf_unmap_sndq_buffers(struct nicvf *nic, struct snd_queue *sq,
+                             int hdr_sqe, u8 subdesc_cnt)
+{
+       u8 idx;
+       struct sq_gather_subdesc *gather;
+
+       /* Unmap DMA mapped skb data buffers */
+       for (idx = 0; idx < subdesc_cnt; idx++) {
+               hdr_sqe++;
+               hdr_sqe &= (sq->dmem.q_len - 1);
+               gather = (struct sq_gather_subdesc *)GET_SQ_DESC(sq, hdr_sqe);
+               /* HW will ensure data coherency, CPU sync not required */
+               dma_unmap_page_attrs(&nic->pdev->dev, gather->addr,
+                                    gather->size, DMA_TO_DEVICE,
+                                    DMA_ATTR_SKIP_CPU_SYNC);
+       }
+}
+
 static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
 {
        struct sk_buff *skb;
+       struct sq_hdr_subdesc *hdr;
+       struct sq_hdr_subdesc *tso_sqe;
 
        if (!sq)
                return;
@@ -379,8 +428,22 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
        smp_rmb();
        while (sq->head != sq->tail) {
                skb = (struct sk_buff *)sq->skbuff[sq->head];
-               if (skb)
-                       dev_kfree_skb_any(skb);
+               if (!skb)
+                       goto next;
+               hdr = (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, sq->head);
+               /* Check for dummy descriptor used for HW TSO offload on 88xx */
+               if (hdr->dont_send) {
+                       /* Get actual TSO descriptors and unmap them */
+                       tso_sqe =
+                        (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, hdr->rsvd2);
+                       nicvf_unmap_sndq_buffers(nic, sq, hdr->rsvd2,
+                                                tso_sqe->subdesc_cnt);
+               } else {
+                       nicvf_unmap_sndq_buffers(nic, sq, sq->head,
+                                                hdr->subdesc_cnt);
+               }
+               dev_kfree_skb_any(skb);
+next:
                sq->head++;
                sq->head &= (sq->dmem.q_len - 1);
        }
@@ -559,9 +622,11 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
        nicvf_send_msg_to_pf(nic, &mbx);
 
        if (!nic->sqs_mode && (qidx == 0)) {
-               /* Enable checking L3/L4 length and TCP/UDP checksums */
+               /* Enable checking L3/L4 length and TCP/UDP checksums
+                * Also allow IPv6 pkts with zero UDP checksum.
+                */
                nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0,
-                                     (BIT(24) | BIT(23) | BIT(21)));
+                                     (BIT(24) | BIT(23) | BIT(21) | BIT(20)));
                nicvf_config_vlan_stripping(nic, nic->netdev->features);
        }
 
@@ -882,6 +947,14 @@ static inline int nicvf_get_sq_desc(struct snd_queue *sq, int desc_cnt)
        return qentry;
 }
 
+/* Rollback to previous tail pointer when descriptors not used */
+static inline void nicvf_rollback_sq_desc(struct snd_queue *sq,
+                                         int qentry, int desc_cnt)
+{
+       sq->tail = qentry;
+       atomic_add(desc_cnt, &sq->free_cnt);
+}
+
 /* Free descriptor back to SQ for future use */
 void nicvf_put_sq_desc(struct snd_queue *sq, int desc_cnt)
 {
@@ -1207,8 +1280,9 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
                        struct sk_buff *skb, u8 sq_num)
 {
        int i, size;
-       int subdesc_cnt, tso_sqe = 0;
+       int subdesc_cnt, hdr_sqe = 0;
        int qentry;
+       u64 dma_addr;
 
        subdesc_cnt = nicvf_sq_subdesc_required(nic, skb);
        if (subdesc_cnt > atomic_read(&sq->free_cnt))
@@ -1223,12 +1297,21 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
        /* Add SQ header subdesc */
        nicvf_sq_add_hdr_subdesc(nic, sq, qentry, subdesc_cnt - 1,
                                 skb, skb->len);
-       tso_sqe = qentry;
+       hdr_sqe = qentry;
 
        /* Add SQ gather subdescs */
        qentry = nicvf_get_nxt_sqentry(sq, qentry);
        size = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len;
-       nicvf_sq_add_gather_subdesc(sq, qentry, size, virt_to_phys(skb->data));
+       /* HW will ensure data coherency, CPU sync not required */
+       dma_addr = dma_map_page_attrs(&nic->pdev->dev, virt_to_page(skb->data),
+                                     offset_in_page(skb->data), size,
+                                     DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+       if (dma_mapping_error(&nic->pdev->dev, dma_addr)) {
+               nicvf_rollback_sq_desc(sq, qentry, subdesc_cnt);
+               return 0;
+       }
+
+       nicvf_sq_add_gather_subdesc(sq, qentry, size, dma_addr);
 
        /* Check for scattered buffer */
        if (!skb_is_nonlinear(skb))
@@ -1241,15 +1324,26 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
 
                qentry = nicvf_get_nxt_sqentry(sq, qentry);
                size = skb_frag_size(frag);
-               nicvf_sq_add_gather_subdesc(sq, qentry, size,
-                                           virt_to_phys(
-                                           skb_frag_address(frag)));
+               dma_addr = dma_map_page_attrs(&nic->pdev->dev,
+                                             skb_frag_page(frag),
+                                             frag->page_offset, size,
+                                             DMA_TO_DEVICE,
+                                             DMA_ATTR_SKIP_CPU_SYNC);
+               if (dma_mapping_error(&nic->pdev->dev, dma_addr)) {
+                       /* Free entire chain of mapped buffers
+                        * here 'i' = frags mapped + above mapped skb->data
+                        */
+                       nicvf_unmap_sndq_buffers(nic, sq, hdr_sqe, i);
+                       nicvf_rollback_sq_desc(sq, qentry, subdesc_cnt);
+                       return 0;
+               }
+               nicvf_sq_add_gather_subdesc(sq, qentry, size, dma_addr);
        }
 
 doorbell:
        if (nic->t88 && skb_shinfo(skb)->gso_size) {
                qentry = nicvf_get_nxt_sqentry(sq, qentry);
-               nicvf_sq_add_cqe_subdesc(sq, qentry, tso_sqe, skb);
+               nicvf_sq_add_cqe_subdesc(sq, qentry, hdr_sqe, skb);
        }
 
        nicvf_sq_doorbell(nic, skb, sq_num, subdesc_cnt);
@@ -1282,6 +1376,7 @@ struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
        int offset;
        u16 *rb_lens = NULL;
        u64 *rb_ptrs = NULL;
+       u64 phys_addr;
 
        rb_lens = (void *)cqe_rx + (3 * sizeof(u64));
        /* Except 88xx pass1 on all other chips CQE_RX2_S is added to
@@ -1296,15 +1391,23 @@ struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
        else
                rb_ptrs = (void *)cqe_rx + (7 * sizeof(u64));
 
-       netdev_dbg(nic->netdev, "%s rb_cnt %d rb0_ptr %llx rb0_sz %d\n",
-                  __func__, cqe_rx->rb_cnt, cqe_rx->rb0_ptr, cqe_rx->rb0_sz);
-
        for (frag = 0; frag < cqe_rx->rb_cnt; frag++) {
                payload_len = rb_lens[frag_num(frag)];
+               phys_addr = nicvf_iova_to_phys(nic, *rb_ptrs);
+               if (!phys_addr) {
+                       if (skb)
+                               dev_kfree_skb_any(skb);
+                       return NULL;
+               }
+
                if (!frag) {
                        /* First fragment */
+                       dma_unmap_page_attrs(&nic->pdev->dev,
+                                            *rb_ptrs - cqe_rx->align_pad,
+                                            RCV_FRAG_LEN, DMA_FROM_DEVICE,
+                                            DMA_ATTR_SKIP_CPU_SYNC);
                        skb = nicvf_rb_ptr_to_skb(nic,
-                                                 *rb_ptrs - cqe_rx->align_pad,
+                                                 phys_addr - cqe_rx->align_pad,
                                                  payload_len);
                        if (!skb)
                                return NULL;
@@ -1312,8 +1415,11 @@ struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
                        skb_put(skb, payload_len);
                } else {
                        /* Add fragments */
-                       page = virt_to_page(phys_to_virt(*rb_ptrs));
-                       offset = phys_to_virt(*rb_ptrs) - page_address(page);
+                       dma_unmap_page_attrs(&nic->pdev->dev, *rb_ptrs,
+                                            RCV_FRAG_LEN, DMA_FROM_DEVICE,
+                                            DMA_ATTR_SKIP_CPU_SYNC);
+                       page = virt_to_page(phys_to_virt(phys_addr));
+                       offset = phys_to_virt(phys_addr) - page_address(page);
                        skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
                                        offset, payload_len, RCV_FRAG_LEN);
                }
index 5cb84da99a2de5bc594464db8759c8359d20447f..10cb4b84625b14a0446996776689ae6733f4ccee 100644 (file)
@@ -87,7 +87,7 @@
 #define RCV_BUF_COUNT          (1ULL << (RBDR_SIZE + 13))
 #define MAX_RCV_BUF_COUNT      (1ULL << (RBDR_SIZE6 + 13))
 #define RBDR_THRESH            (RCV_BUF_COUNT / 2)
-#define DMA_BUFFER_LEN         2048 /* In multiples of 128bytes */
+#define DMA_BUFFER_LEN         1536 /* In multiples of 128bytes */
 #define RCV_FRAG_LEN    (SKB_DATA_ALIGN(DMA_BUFFER_LEN + NET_SKB_PAD) + \
                         SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
 
@@ -301,6 +301,8 @@ struct queue_set {
 
 #define        CQ_ERR_MASK     (CQ_WR_FULL | CQ_WR_DISABLE | CQ_WR_FAULT)
 
+void nicvf_unmap_sndq_buffers(struct nicvf *nic, struct snd_queue *sq,
+                             int hdr_sqe, u8 subdesc_cnt);
 void nicvf_config_vlan_stripping(struct nicvf *nic,
                                 netdev_features_t features);
 int nicvf_set_qset_resources(struct nicvf *nic);
index 4c8e8cf730bbc2ee1d488d42d9d42163d442fb75..64a1095e4d1495c1e32c3ff7008882789f6b6f6e 100644 (file)
@@ -123,14 +123,44 @@ static int bgx_poll_reg(struct bgx *bgx, u8 lmac, u64 reg, u64 mask, bool zero)
        return 1;
 }
 
+static int max_bgx_per_node;
+static void set_max_bgx_per_node(struct pci_dev *pdev)
+{
+       u16 sdevid;
+
+       if (max_bgx_per_node)
+               return;
+
+       pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &sdevid);
+       switch (sdevid) {
+       case PCI_SUBSYS_DEVID_81XX_BGX:
+               max_bgx_per_node = MAX_BGX_PER_CN81XX;
+               break;
+       case PCI_SUBSYS_DEVID_83XX_BGX:
+               max_bgx_per_node = MAX_BGX_PER_CN83XX;
+               break;
+       case PCI_SUBSYS_DEVID_88XX_BGX:
+       default:
+               max_bgx_per_node = MAX_BGX_PER_CN88XX;
+               break;
+       }
+}
+
+static struct bgx *get_bgx(int node, int bgx_idx)
+{
+       int idx = (node * max_bgx_per_node) + bgx_idx;
+
+       return bgx_vnic[idx];
+}
+
 /* Return number of BGX present in HW */
 unsigned bgx_get_map(int node)
 {
        int i;
        unsigned map = 0;
 
-       for (i = 0; i < MAX_BGX_PER_NODE; i++) {
-               if (bgx_vnic[(node * MAX_BGX_PER_NODE) + i])
+       for (i = 0; i < max_bgx_per_node; i++) {
+               if (bgx_vnic[(node * max_bgx_per_node) + i])
                        map |= (1 << i);
        }
 
@@ -143,7 +173,7 @@ int bgx_get_lmac_count(int node, int bgx_idx)
 {
        struct bgx *bgx;
 
-       bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       bgx = get_bgx(node, bgx_idx);
        if (bgx)
                return bgx->lmac_count;
 
@@ -158,7 +188,7 @@ void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status)
        struct bgx *bgx;
        struct lmac *lmac;
 
-       bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       bgx = get_bgx(node, bgx_idx);
        if (!bgx)
                return;
 
@@ -172,7 +202,7 @@ EXPORT_SYMBOL(bgx_get_lmac_link_state);
 
 const u8 *bgx_get_lmac_mac(int node, int bgx_idx, int lmacid)
 {
-       struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       struct bgx *bgx = get_bgx(node, bgx_idx);
 
        if (bgx)
                return bgx->lmac[lmacid].mac;
@@ -183,7 +213,7 @@ EXPORT_SYMBOL(bgx_get_lmac_mac);
 
 void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac)
 {
-       struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       struct bgx *bgx = get_bgx(node, bgx_idx);
 
        if (!bgx)
                return;
@@ -194,7 +224,7 @@ EXPORT_SYMBOL(bgx_set_lmac_mac);
 
 void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
 {
-       struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       struct bgx *bgx = get_bgx(node, bgx_idx);
        struct lmac *lmac;
        u64 cfg;
 
@@ -217,7 +247,7 @@ EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
 void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
 {
        struct pfc *pfc = (struct pfc *)pause;
-       struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
+       struct bgx *bgx = get_bgx(node, bgx_idx);
        struct lmac *lmac;
        u64 cfg;
 
@@ -237,7 +267,7 @@ EXPORT_SYMBOL(bgx_lmac_get_pfc);
 void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause)
 {
        struct pfc *pfc = (struct pfc *)pause;
-       struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
+       struct bgx *bgx = get_bgx(node, bgx_idx);
        struct lmac *lmac;
        u64 cfg;
 
@@ -369,7 +399,7 @@ u64 bgx_get_rx_stats(int node, int bgx_idx, int lmac, int idx)
 {
        struct bgx *bgx;
 
-       bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       bgx = get_bgx(node, bgx_idx);
        if (!bgx)
                return 0;
 
@@ -383,7 +413,7 @@ u64 bgx_get_tx_stats(int node, int bgx_idx, int lmac, int idx)
 {
        struct bgx *bgx;
 
-       bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       bgx = get_bgx(node, bgx_idx);
        if (!bgx)
                return 0;
 
@@ -411,7 +441,7 @@ void bgx_lmac_internal_loopback(int node, int bgx_idx,
        struct lmac *lmac;
        u64    cfg;
 
-       bgx = bgx_vnic[(node * MAX_BGX_PER_NODE) + bgx_idx];
+       bgx = get_bgx(node, bgx_idx);
        if (!bgx)
                return;
 
@@ -1011,12 +1041,6 @@ static void bgx_print_qlm_mode(struct bgx *bgx, u8 lmacid)
                        dev_info(dev, "%s: 40G_KR4\n", (char *)str);
                break;
        case BGX_MODE_QSGMII:
-               if ((lmacid == 0) &&
-                   (bgx_get_lane2sds_cfg(bgx, lmac) != lmacid))
-                       return;
-               if ((lmacid == 2) &&
-                   (bgx_get_lane2sds_cfg(bgx, lmac) == lmacid))
-                       return;
                dev_info(dev, "%s: QSGMII\n", (char *)str);
                break;
        case BGX_MODE_RGMII:
@@ -1334,11 +1358,13 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_release_regions;
        }
 
+       set_max_bgx_per_node(pdev);
+
        pci_read_config_word(pdev, PCI_DEVICE_ID, &sdevid);
        if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) {
                bgx->bgx_id = (pci_resource_start(pdev,
                        PCI_CFG_REG_BAR_NUM) >> 24) & BGX_ID_MASK;
-               bgx->bgx_id += nic_get_node_id(pdev) * MAX_BGX_PER_NODE;
+               bgx->bgx_id += nic_get_node_id(pdev) * max_bgx_per_node;
                bgx->max_lmac = MAX_LMAC_PER_BGX;
                bgx_vnic[bgx->bgx_id] = bgx;
        } else {
index a60f189429bb658cb5ab8383982f86ddd9090fc3..c5080f2cead5d0efc435fd827038eb7dbe4b5830 100644 (file)
@@ -22,7 +22,6 @@
 #define    MAX_BGX_PER_CN88XX                  2
 #define    MAX_BGX_PER_CN81XX                  3 /* 2 BGXs + 1 RGX */
 #define    MAX_BGX_PER_CN83XX                  4
-#define    MAX_BGX_PER_NODE                    4
 #define    MAX_LMAC_PER_BGX                    4
 #define    MAX_BGX_CHANS_PER_LMAC              16
 #define    MAX_DMAC_PER_LMAC                   8
index 275c2e2349ad92de224df1939769238d83ea5f3b..c44036d5761a4cbec301afb63393d49b47bac867 100644 (file)
@@ -2589,8 +2589,6 @@ static int emac_dt_mdio_probe(struct emac_instance *dev)
 static int emac_dt_phy_connect(struct emac_instance *dev,
                               struct device_node *phy_handle)
 {
-       int res;
-
        dev->phy.def = devm_kzalloc(&dev->ofdev->dev, sizeof(*dev->phy.def),
                                    GFP_KERNEL);
        if (!dev->phy.def)
@@ -2617,7 +2615,7 @@ static int emac_dt_phy_probe(struct emac_instance *dev)
 {
        struct device_node *np = dev->ofdev->dev.of_node;
        struct device_node *phy_handle;
-       int res = 0;
+       int res = 1;
 
        phy_handle = of_parse_phandle(np, "phy-handle", 0);
 
@@ -2714,13 +2712,24 @@ static int emac_init_phy(struct emac_instance *dev)
        if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII)) {
                int res = emac_dt_phy_probe(dev);
 
-               mutex_unlock(&emac_phy_map_lock);
-               if (!res)
+               switch (res) {
+               case 1:
+                       /* No phy-handle property configured.
+                        * Continue with the existing phy probe
+                        * and setup code.
+                        */
+                       break;
+
+               case 0:
+                       mutex_unlock(&emac_phy_map_lock);
                        goto init_phy;
 
-               dev_err(&dev->ofdev->dev, "failed to attach dt phy (%d).\n",
-                       res);
-               return res;
+               default:
+                       mutex_unlock(&emac_phy_map_lock);
+                       dev_err(&dev->ofdev->dev, "failed to attach dt phy (%d).\n",
+                               res);
+                       return res;
+               }
        }
 
        if (dev->phy_address != 0xffffffff)
index 9198e6bd5160f9559075f348a6d595252ea88819..b23d6545f83562b8d9d12b4a885514dfd5257743 100644 (file)
@@ -404,7 +404,7 @@ static int ibmvnic_open(struct net_device *netdev)
        send_map_query(adapter);
        for (i = 0; i < rxadd_subcrqs; i++) {
                init_rx_pool(adapter, &adapter->rx_pool[i],
-                            IBMVNIC_BUFFS_PER_POOL, i,
+                            adapter->req_rx_add_entries_per_subcrq, i,
                             be64_to_cpu(size_array[i]), 1);
                if (alloc_rx_pool(adapter, &adapter->rx_pool[i])) {
                        dev_err(dev, "Couldn't alloc rx pool\n");
@@ -419,23 +419,23 @@ static int ibmvnic_open(struct net_device *netdev)
        for (i = 0; i < tx_subcrqs; i++) {
                tx_pool = &adapter->tx_pool[i];
                tx_pool->tx_buff =
-                   kcalloc(adapter->max_tx_entries_per_subcrq,
+                   kcalloc(adapter->req_tx_entries_per_subcrq,
                            sizeof(struct ibmvnic_tx_buff), GFP_KERNEL);
                if (!tx_pool->tx_buff)
                        goto tx_pool_alloc_failed;
 
                if (alloc_long_term_buff(adapter, &tx_pool->long_term_buff,
-                                        adapter->max_tx_entries_per_subcrq *
+                                        adapter->req_tx_entries_per_subcrq *
                                         adapter->req_mtu))
                        goto tx_ltb_alloc_failed;
 
                tx_pool->free_map =
-                   kcalloc(adapter->max_tx_entries_per_subcrq,
+                   kcalloc(adapter->req_tx_entries_per_subcrq,
                            sizeof(int), GFP_KERNEL);
                if (!tx_pool->free_map)
                        goto tx_fm_alloc_failed;
 
-               for (j = 0; j < adapter->max_tx_entries_per_subcrq; j++)
+               for (j = 0; j < adapter->req_tx_entries_per_subcrq; j++)
                        tx_pool->free_map[j] = j;
 
                tx_pool->consumer_index = 0;
@@ -705,6 +705,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        u8 *hdrs = (u8 *)&adapter->tx_rx_desc_req;
        struct device *dev = &adapter->vdev->dev;
        struct ibmvnic_tx_buff *tx_buff = NULL;
+       struct ibmvnic_sub_crq_queue *tx_scrq;
        struct ibmvnic_tx_pool *tx_pool;
        unsigned int tx_send_failed = 0;
        unsigned int tx_map_failed = 0;
@@ -724,6 +725,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        int ret = 0;
 
        tx_pool = &adapter->tx_pool[queue_num];
+       tx_scrq = adapter->tx_scrq[queue_num];
        txq = netdev_get_tx_queue(netdev, skb_get_queue_mapping(skb));
        handle_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
                                   be32_to_cpu(adapter->login_rsp_buf->
@@ -744,7 +746,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 
        tx_pool->consumer_index =
            (tx_pool->consumer_index + 1) %
-               adapter->max_tx_entries_per_subcrq;
+               adapter->req_tx_entries_per_subcrq;
 
        tx_buff = &tx_pool->tx_buff[index];
        tx_buff->skb = skb;
@@ -817,7 +819,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 
                if (tx_pool->consumer_index == 0)
                        tx_pool->consumer_index =
-                               adapter->max_tx_entries_per_subcrq - 1;
+                               adapter->req_tx_entries_per_subcrq - 1;
                else
                        tx_pool->consumer_index--;
 
@@ -826,6 +828,14 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                ret = NETDEV_TX_BUSY;
                goto out;
        }
+
+       atomic_inc(&tx_scrq->used);
+
+       if (atomic_read(&tx_scrq->used) >= adapter->req_tx_entries_per_subcrq) {
+               netdev_info(netdev, "Stopping queue %d\n", queue_num);
+               netif_stop_subqueue(netdev, queue_num);
+       }
+
        tx_packets++;
        tx_bytes += skb->len;
        txq->trans_start = jiffies;
@@ -1213,6 +1223,7 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter
        scrq->adapter = adapter;
        scrq->size = 4 * PAGE_SIZE / sizeof(*scrq->msgs);
        scrq->cur = 0;
+       atomic_set(&scrq->used, 0);
        scrq->rx_skb_top = NULL;
        spin_lock_init(&scrq->lock);
 
@@ -1246,6 +1257,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter)
                                release_sub_crq_queue(adapter,
                                                      adapter->tx_scrq[i]);
                        }
+               kfree(adapter->tx_scrq);
                adapter->tx_scrq = NULL;
        }
 
@@ -1258,6 +1270,7 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter)
                                release_sub_crq_queue(adapter,
                                                      adapter->rx_scrq[i]);
                        }
+               kfree(adapter->rx_scrq);
                adapter->rx_scrq = NULL;
        }
 }
@@ -1355,14 +1368,28 @@ restart_loop:
                                                 DMA_TO_DEVICE);
                        }
 
-                       if (txbuff->last_frag)
+                       if (txbuff->last_frag) {
+                               atomic_dec(&scrq->used);
+
+                               if (atomic_read(&scrq->used) <=
+                                   (adapter->req_tx_entries_per_subcrq / 2) &&
+                                   netif_subqueue_stopped(adapter->netdev,
+                                                          txbuff->skb)) {
+                                       netif_wake_subqueue(adapter->netdev,
+                                                           scrq->pool_index);
+                                       netdev_dbg(adapter->netdev,
+                                                  "Started queue %d\n",
+                                                  scrq->pool_index);
+                               }
+
                                dev_kfree_skb_any(txbuff->skb);
+                       }
 
                        adapter->tx_pool[pool].free_map[adapter->tx_pool[pool].
                                                     producer_index] = index;
                        adapter->tx_pool[pool].producer_index =
                            (adapter->tx_pool[pool].producer_index + 1) %
-                           adapter->max_tx_entries_per_subcrq;
+                           adapter->req_tx_entries_per_subcrq;
                }
                /* remove tx_comp scrq*/
                next->tx_comp.first = 0;
index 422824f1f42a8accdbbe7a97c70baa9882fbcce8..1993b42666f73d659773b6b88bcd8e8552ac97b7 100644 (file)
@@ -863,6 +863,7 @@ struct ibmvnic_sub_crq_queue {
        spinlock_t lock;
        struct sk_buff *rx_skb_top;
        struct ibmvnic_adapter *adapter;
+       atomic_t used;
 };
 
 struct ibmvnic_long_term_buff {
index e8c105164931f31ff0cf5ed12acef455d0010eda..0e0fa70305659521ed50d1cf1bc40fd38aa3ad04 100644 (file)
@@ -2305,6 +2305,17 @@ static int sync_toggles(struct mlx4_dev *dev)
                rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read));
                if (wr_toggle == 0xffffffff || rd_toggle == 0xffffffff) {
                        /* PCI might be offline */
+
+                       /* If device removal has been requested,
+                        * do not continue retrying.
+                        */
+                       if (dev->persist->interface_state &
+                           MLX4_INTERFACE_STATE_NOWAIT) {
+                               mlx4_warn(dev,
+                                         "communication channel is offline\n");
+                               return -EIO;
+                       }
+
                        msleep(100);
                        wr_toggle = swab32(readl(&priv->mfunc.comm->
                                           slave_write));
index 21377c315083b686d8db25033583dd020d7e50a6..703205475524d689cd2762f2d2ce3abfd2b6ebcb 100644 (file)
@@ -1940,6 +1940,14 @@ static int mlx4_comm_check_offline(struct mlx4_dev *dev)
                               (u32)(1 << COMM_CHAN_OFFLINE_OFFSET));
                if (!offline_bit)
                        return 0;
+
+               /* If device removal has been requested,
+                * do not continue retrying.
+                */
+               if (dev->persist->interface_state &
+                   MLX4_INTERFACE_STATE_NOWAIT)
+                       break;
+
                /* There are cases as part of AER/Reset flow that PF needs
                 * around 100 msec to load. We therefore sleep for 100 msec
                 * to allow other tasks to make use of that CPU during this
@@ -3955,6 +3963,9 @@ static void mlx4_remove_one(struct pci_dev *pdev)
        struct devlink *devlink = priv_to_devlink(priv);
        int active_vfs = 0;
 
+       if (mlx4_is_slave(dev))
+               persist->interface_state |= MLX4_INTERFACE_STATE_NOWAIT;
+
        mutex_lock(&persist->interface_state_mutex);
        persist->interface_state |= MLX4_INTERFACE_STATE_DELETION;
        mutex_unlock(&persist->interface_state_mutex);
index ddb4ca4ff930a74b38a97b04b98ad54262da1a7b..117170014e8897f0f91cfc25464e3a03aba044ec 100644 (file)
@@ -14,6 +14,7 @@ config MLX5_CORE
 config MLX5_CORE_EN
        bool "Mellanox Technologies ConnectX-4 Ethernet support"
        depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
+       depends on IPV6=y || IPV6=n || MLX5_CORE=m
        imply PTP_1588_CLOCK
        default n
        ---help---
index caa837e5e2b991fc3666776d2050fe20b1c6c7f6..a380353a78c2d349291e33aa3a1ef7af837111c2 100644 (file)
@@ -361,6 +361,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
        case MLX5_CMD_OP_ALLOC_Q_COUNTER:
        case MLX5_CMD_OP_QUERY_Q_COUNTER:
+       case MLX5_CMD_OP_SET_RATE_LIMIT:
+       case MLX5_CMD_OP_QUERY_RATE_LIMIT:
        case MLX5_CMD_OP_ALLOC_PD:
        case MLX5_CMD_OP_ALLOC_UAR:
        case MLX5_CMD_OP_CONFIG_INT_MODERATION:
@@ -497,6 +499,8 @@ const char *mlx5_command_str(int command)
        MLX5_COMMAND_STR_CASE(ALLOC_Q_COUNTER);
        MLX5_COMMAND_STR_CASE(DEALLOC_Q_COUNTER);
        MLX5_COMMAND_STR_CASE(QUERY_Q_COUNTER);
+       MLX5_COMMAND_STR_CASE(SET_RATE_LIMIT);
+       MLX5_COMMAND_STR_CASE(QUERY_RATE_LIMIT);
        MLX5_COMMAND_STR_CASE(ALLOC_PD);
        MLX5_COMMAND_STR_CASE(DEALLOC_PD);
        MLX5_COMMAND_STR_CASE(ALLOC_UAR);
index f6a6ded204f61cda53c6233d80b3db7cde678c6e..dc52053128bc752ccd398449330c24c0bdf8b3a1 100644 (file)
@@ -928,10 +928,6 @@ void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv);
 int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
 void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
 u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout);
-void mlx5e_add_vxlan_port(struct net_device *netdev,
-                         struct udp_tunnel_info *ti);
-void mlx5e_del_vxlan_port(struct net_device *netdev,
-                         struct udp_tunnel_info *ti);
 
 int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
                            void *sp);
index 0523ed47f597c715296c5ea843245625bf3dac62..8fa23f6a1f67f6494168455a58c5a7b1ee35cae5 100644 (file)
@@ -302,6 +302,9 @@ static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_dcbx *dcbx = &priv->dcbx;
 
+       if (mode & DCB_CAP_DCBX_LLD_MANAGED)
+               return 1;
+
        if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
                if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
                        return 0;
@@ -315,13 +318,10 @@ static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
                return 1;
        }
 
-       if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
+       if (!(mode & DCB_CAP_DCBX_HOST))
                return 1;
 
-       if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
-           !(mode & DCB_CAP_DCBX_VER_CEE) ||
-           !(mode & DCB_CAP_DCBX_VER_IEEE) ||
-           !(mode & DCB_CAP_DCBX_HOST))
+       if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
                return 1;
 
        return 0;
index 8ef64c4db2c21ad6a752338cb32b054a5e5f3968..66c133757a5ee8daae122e93322306b1c5c44336 100644 (file)
@@ -3100,8 +3100,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
                                            vf_stats);
 }
 
-void mlx5e_add_vxlan_port(struct net_device *netdev,
-                         struct udp_tunnel_info *ti)
+static void mlx5e_add_vxlan_port(struct net_device *netdev,
+                                struct udp_tunnel_info *ti)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
@@ -3114,8 +3114,8 @@ void mlx5e_add_vxlan_port(struct net_device *netdev,
        mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
 }
 
-void mlx5e_del_vxlan_port(struct net_device *netdev,
-                         struct udp_tunnel_info *ti)
+static void mlx5e_del_vxlan_port(struct net_device *netdev,
+                                struct udp_tunnel_info *ti)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
index 2c864574a9d5faeaa3b329f3bc0ab0d4e0cc7b55..f621373bd7a564aca3ddd1247117467daffc72df 100644 (file)
@@ -393,8 +393,6 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
        .ndo_get_phys_port_name  = mlx5e_rep_get_phys_port_name,
        .ndo_setup_tc            = mlx5e_rep_ndo_setup_tc,
        .ndo_get_stats64         = mlx5e_rep_get_stats,
-       .ndo_udp_tunnel_add      = mlx5e_add_vxlan_port,
-       .ndo_udp_tunnel_del      = mlx5e_del_vxlan_port,
        .ndo_has_offload_stats   = mlx5e_has_offload_stats,
        .ndo_get_offload_stats   = mlx5e_get_offload_stats,
 };
index 3d371688fbbbf3544170468840829e15095ea3a0..bafcb349a50c6d3809aa329d43382e51dbd3ffe4 100644 (file)
@@ -601,6 +601,10 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
        if (lro_num_seg > 1) {
                mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt);
                skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg);
+               /* Subtract one since we already counted this as one
+                * "regular" packet in mlx5e_complete_rx_cqe()
+                */
+               rq->stats.packets += lro_num_seg - 1;
                rq->stats.lro_packets++;
                rq->stats.lro_bytes += cqe_bcnt;
        }
index 31e3cb7ee5feeb35ce383c5582bc800733b81643..5621dcfda4f1868c6bccdff9cd220b7a43d46dd3 100644 (file)
@@ -204,9 +204,6 @@ mlx5e_test_loopback_validate(struct sk_buff *skb,
        struct iphdr *iph;
 
        /* We are only going to peek, no need to clone the SKB */
-       if (skb->protocol != htons(ETH_P_IP))
-               goto out;
-
        if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb))
                goto out;
 
@@ -249,7 +246,7 @@ static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
        lbtp->loopback_ok = false;
        init_completion(&lbtp->comp);
 
-       lbtp->pt.type = htons(ETH_P_ALL);
+       lbtp->pt.type = htons(ETH_P_IP);
        lbtp->pt.func = mlx5e_test_loopback_validate;
        lbtp->pt.dev = priv->netdev;
        lbtp->pt.af_packet_priv = lbtp;
index 44406a5ec15d96a6ca45d30b609864f8cccb07e1..fade7233dac5256cb69d0fc67b0c3cb1a4444da5 100644 (file)
 #include "eswitch.h"
 #include "vxlan.h"
 
+enum {
+       MLX5E_TC_FLOW_ESWITCH   = BIT(0),
+};
+
 struct mlx5e_tc_flow {
        struct rhash_head       node;
        u64                     cookie;
+       u8                      flags;
        struct mlx5_flow_handle *rule;
        struct list_head        encap; /* flows sharing the same encap */
        struct mlx5_esw_flow_attr *attr;
@@ -128,6 +133,23 @@ err_create_ft:
        return rule;
 }
 
+static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
+                                 struct mlx5e_tc_flow *flow)
+{
+       struct mlx5_fc *counter = NULL;
+
+       if (!IS_ERR(flow->rule)) {
+               counter = mlx5_flow_rule_counter(flow->rule);
+               mlx5_del_flow_rules(flow->rule);
+               mlx5_fc_destroy(priv->mdev, counter);
+       }
+
+       if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
+               mlx5_destroy_flow_table(priv->fs.tc.t);
+               priv->fs.tc.t = NULL;
+       }
+}
+
 static struct mlx5_flow_handle *
 mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
                      struct mlx5_flow_spec *spec,
@@ -144,7 +166,24 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
 }
 
 static void mlx5e_detach_encap(struct mlx5e_priv *priv,
-                              struct mlx5e_tc_flow *flow) {
+                              struct mlx5e_tc_flow *flow);
+
+static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+                                 struct mlx5e_tc_flow *flow)
+{
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+       mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->attr);
+
+       mlx5_eswitch_del_vlan_action(esw, flow->attr);
+
+       if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
+               mlx5e_detach_encap(priv, flow);
+}
+
+static void mlx5e_detach_encap(struct mlx5e_priv *priv,
+                              struct mlx5e_tc_flow *flow)
+{
        struct list_head *next = flow->encap.next;
 
        list_del(&flow->encap);
@@ -168,25 +207,10 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
 static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow)
 {
-       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
-       struct mlx5_fc *counter = NULL;
-
-       if (!IS_ERR(flow->rule)) {
-               counter = mlx5_flow_rule_counter(flow->rule);
-               mlx5_del_flow_rules(flow->rule);
-               mlx5_fc_destroy(priv->mdev, counter);
-       }
-
-       if (esw && esw->mode == SRIOV_OFFLOADS) {
-               mlx5_eswitch_del_vlan_action(esw, flow->attr);
-               if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
-                       mlx5e_detach_encap(priv, flow);
-       }
-
-       if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
-               mlx5_destroy_flow_table(priv->fs.tc.t);
-               priv->fs.tc.t = NULL;
-       }
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               mlx5e_tc_del_fdb_flow(priv, flow);
+       else
+               mlx5e_tc_del_nic_flow(priv, flow);
 }
 
 static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
@@ -243,12 +267,15 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
                        skb_flow_dissector_target(f->dissector,
                                                  FLOW_DISSECTOR_KEY_ENC_PORTS,
                                                  f->mask);
+               struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+               struct net_device *up_dev = mlx5_eswitch_get_uplink_netdev(esw);
+               struct mlx5e_priv *up_priv = netdev_priv(up_dev);
 
                /* Full udp dst port must be given */
                if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst)))
                        goto vxlan_match_offload_err;
 
-               if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->dst)) &&
+               if (mlx5e_vxlan_lookup_port(up_priv, be16_to_cpu(key->dst)) &&
                    MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap))
                        parse_vxlan_attr(spec, f);
                else {
@@ -598,6 +625,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
 }
 
 static int parse_cls_flower(struct mlx5e_priv *priv,
+                           struct mlx5e_tc_flow *flow,
                            struct mlx5_flow_spec *spec,
                            struct tc_cls_flower_offload *f)
 {
@@ -609,7 +637,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
 
        err = __parse_cls_flower(priv, spec, f, &min_inline);
 
-       if (!err && esw->mode == SRIOV_OFFLOADS &&
+       if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH) &&
            rep->vport != FDB_UPLINK_VPORT) {
                if (min_inline > esw->offloads.inline_mode) {
                        netdev_warn(priv->netdev,
@@ -970,6 +998,8 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                              struct mlx5_esw_flow_attr *attr)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       struct net_device *up_dev = mlx5_eswitch_get_uplink_netdev(esw);
+       struct mlx5e_priv *up_priv = netdev_priv(up_dev);
        unsigned short family = ip_tunnel_info_af(tun_info);
        struct ip_tunnel_key *key = &tun_info->key;
        struct mlx5_encap_entry *e;
@@ -990,7 +1020,7 @@ vxlan_encap_offload_err:
                return -EOPNOTSUPP;
        }
 
-       if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->tp_dst)) &&
+       if (mlx5e_vxlan_lookup_port(up_priv, be16_to_cpu(key->tp_dst)) &&
            MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) {
                tunnel_type = MLX5_HEADER_TYPE_VXLAN;
        } else {
@@ -1106,14 +1136,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                }
 
                if (is_tcf_vlan(a)) {
-                       if (tcf_vlan_action(a) == VLAN_F_POP) {
+                       if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
-                       } else if (tcf_vlan_action(a) == VLAN_F_PUSH) {
+                       } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
                                if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q))
                                        return -EOPNOTSUPP;
 
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
                                attr->vlan = tcf_vlan_push_vid(a);
+                       } else { /* action is TCA_VLAN_ACT_MODIFY */
+                               return -EOPNOTSUPP;
                        }
                        continue;
                }
@@ -1132,23 +1164,19 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
                           struct tc_cls_flower_offload *f)
 {
        struct mlx5e_tc_table *tc = &priv->fs.tc;
-       int err = 0;
-       bool fdb_flow = false;
+       int err, attr_size = 0;
        u32 flow_tag, action;
        struct mlx5e_tc_flow *flow;
        struct mlx5_flow_spec *spec;
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       u8 flow_flags = 0;
 
-       if (esw && esw->mode == SRIOV_OFFLOADS)
-               fdb_flow = true;
-
-       if (fdb_flow)
-               flow = kzalloc(sizeof(*flow) +
-                              sizeof(struct mlx5_esw_flow_attr),
-                              GFP_KERNEL);
-       else
-               flow = kzalloc(sizeof(*flow), GFP_KERNEL);
+       if (esw && esw->mode == SRIOV_OFFLOADS) {
+               flow_flags = MLX5E_TC_FLOW_ESWITCH;
+               attr_size  = sizeof(struct mlx5_esw_flow_attr);
+       }
 
+       flow = kzalloc(sizeof(*flow) + attr_size, GFP_KERNEL);
        spec = mlx5_vzalloc(sizeof(*spec));
        if (!spec || !flow) {
                err = -ENOMEM;
@@ -1156,12 +1184,13 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
        }
 
        flow->cookie = f->cookie;
+       flow->flags = flow_flags;
 
-       err = parse_cls_flower(priv, spec, f);
+       err = parse_cls_flower(priv, flow, spec, f);
        if (err < 0)
                goto err_free;
 
-       if (fdb_flow) {
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
                flow->attr  = (struct mlx5_esw_flow_attr *)(flow + 1);
                err = parse_tc_fdb_actions(priv, f->exts, flow);
                if (err < 0)
index f193128bac4b8c18504ec1f5905def3baa5c4633..57f5e2d7ebd1a91a1a1cf618e60caf1f015914a3 100644 (file)
@@ -274,15 +274,18 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
                        sq->stats.tso_bytes += skb->len - ihs;
                }
 
+               sq->stats.packets += skb_shinfo(skb)->gso_segs;
                num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs;
        } else {
                bf = sq->bf_budget &&
                     !skb->xmit_more &&
                     !skb_shinfo(skb)->nr_frags;
                ihs = mlx5e_get_inline_hdr_size(sq, skb, bf);
+               sq->stats.packets++;
                num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN);
        }
 
+       sq->stats.bytes += num_bytes;
        wi->num_bytes = num_bytes;
 
        ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
@@ -381,8 +384,6 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
        if (bf)
                sq->bf_budget--;
 
-       sq->stats.packets++;
-       sq->stats.bytes += num_bytes;
        return NETDEV_TX_OK;
 
 dma_unmap_wqe_err:
index 5b78883d565413ec59a00ecba4ddb483e4eecd3f..ad329b1680b455ddd4cdfda56bf512bfbea37529 100644 (file)
@@ -209,6 +209,7 @@ struct mlx5_esw_offload {
        struct mlx5_eswitch_rep *vport_reps;
        DECLARE_HASHTABLE(encap_tbl, 8);
        u8 inline_mode;
+       u64 num_flows;
 };
 
 struct mlx5_eswitch {
@@ -271,6 +272,11 @@ struct mlx5_flow_handle *
 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                                struct mlx5_flow_spec *spec,
                                struct mlx5_esw_flow_attr *attr);
+void
+mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw,
+                               struct mlx5_flow_handle *rule,
+                               struct mlx5_esw_flow_attr *attr);
+
 struct mlx5_flow_handle *
 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn);
 
index 4f5b0d47d5f38237129a7c90a1240b8615615d32..307ec6c5fd3b62dffe6cfd5f2541dad9fc155fc3 100644 (file)
@@ -93,10 +93,27 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                                   spec, &flow_act, dest, i);
        if (IS_ERR(rule))
                mlx5_fc_destroy(esw->dev, counter);
+       else
+               esw->offloads.num_flows++;
 
        return rule;
 }
 
+void
+mlx5_eswitch_del_offloaded_rule(struct mlx5_eswitch *esw,
+                               struct mlx5_flow_handle *rule,
+                               struct mlx5_esw_flow_attr *attr)
+{
+       struct mlx5_fc *counter = NULL;
+
+       if (!IS_ERR(rule)) {
+               counter = mlx5_flow_rule_counter(rule);
+               mlx5_del_flow_rules(rule);
+               mlx5_fc_destroy(esw->dev, counter);
+               esw->offloads.num_flows--;
+       }
+}
+
 static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val)
 {
        struct mlx5_eswitch_rep *rep;
@@ -908,6 +925,11 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
            MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
                return -EOPNOTSUPP;
 
+       if (esw->offloads.num_flows > 0) {
+               esw_warn(dev, "Can't set inline mode when flows are configured\n");
+               return -EOPNOTSUPP;
+       }
+
        err = esw_inline_mode_from_devlink(mode, &mlx5_mode);
        if (err)
                goto out;
index 2478516a61e2ea547f5ae8af0c3aae7228e64db9..ded27bb9a3b6049ff4bad1606443dbeff53be8f1 100644 (file)
@@ -1136,7 +1136,7 @@ static struct mlx5_flow_group *create_autogroup(struct mlx5_flow_table *ft,
                                                u32 *match_criteria)
 {
        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       struct list_head *prev = ft->node.children.prev;
+       struct list_head *prev = &ft->node.children;
        unsigned int candidate_index = 0;
        struct mlx5_flow_group *fg;
        void *match_criteria_addr;
index c4242a4e81309f0d90a0cae8bdfc09fd39da5649..60154a175bd3866f2b461a357c60d86283afde12 100644 (file)
@@ -87,7 +87,7 @@ static struct mlx5_profile profile[] = {
        [2] = {
                .mask           = MLX5_PROF_MASK_QP_SIZE |
                                  MLX5_PROF_MASK_MR_CACHE,
-               .log_max_qp     = 17,
+               .log_max_qp     = 18,
                .mr_cache[0]    = {
                        .size   = 500,
                        .limit  = 250
@@ -1352,6 +1352,7 @@ static int init_one(struct pci_dev *pdev,
        if (err)
                goto clean_load;
 
+       pci_save_state(pdev);
        return 0;
 
 clean_load:
@@ -1407,9 +1408,8 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
 
        mlx5_enter_error_state(dev);
        mlx5_unload_one(dev, priv, false);
-       /* In case of kernel call save the pci state and drain the health wq */
+       /* In case of kernel call drain the health wq */
        if (state) {
-               pci_save_state(pdev);
                mlx5_drain_health_wq(dev);
                mlx5_pci_disable_device(dev);
        }
@@ -1461,6 +1461,7 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
 
        pci_set_master(pdev);
        pci_restore_state(pdev);
+       pci_save_state(pdev);
 
        if (wait_vital(pdev)) {
                dev_err(&pdev->dev, "%s: wait_vital timed out\n", __func__);
index 0899e2d310e26269a5c3d025b7afeeb1516bf21e..d9616daf8a705645eb5b14e5af889e0b5020ab0d 100644 (file)
@@ -769,7 +769,7 @@ static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid)
 #define MLXSW_REG_SPVM_ID 0x200F
 #define MLXSW_REG_SPVM_BASE_LEN 0x04 /* base length, without records */
 #define MLXSW_REG_SPVM_REC_LEN 0x04 /* record length */
-#define MLXSW_REG_SPVM_REC_MAX_COUNT 256
+#define MLXSW_REG_SPVM_REC_MAX_COUNT 255
 #define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN +  \
                    MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT)
 
@@ -1702,7 +1702,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload,
 #define MLXSW_REG_SPVMLR_ID 0x2020
 #define MLXSW_REG_SPVMLR_BASE_LEN 0x04 /* base length, without records */
 #define MLXSW_REG_SPVMLR_REC_LEN 0x04 /* record length */
-#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 256
+#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 255
 #define MLXSW_REG_SPVMLR_LEN (MLXSW_REG_SPVMLR_BASE_LEN + \
                              MLXSW_REG_SPVMLR_REC_LEN * \
                              MLXSW_REG_SPVMLR_REC_MAX_COUNT)
index 22ab429253778d2a22e4c59c742f8f6778e57f40..ae6cccc666e4619bbb1a8360b5cc090d303da60b 100644 (file)
@@ -303,11 +303,11 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, mlxsw_sp_port->dev,
                                           ingress,
                                           MLXSW_SP_ACL_PROFILE_FLOWER);
-       if (WARN_ON(IS_ERR(ruleset)))
+       if (IS_ERR(ruleset))
                return;
 
        rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset, f->cookie);
-       if (!WARN_ON(!rule)) {
+       if (rule) {
                mlxsw_sp_acl_rule_del(mlxsw_sp, rule);
                mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule);
        }
index d42d03df751acbb32dd725c769bbf5d56aeb72e4..7e3a6fed3da6d94fe47139aef697563b56726950 100644 (file)
@@ -422,8 +422,9 @@ static void qed_cxt_set_proto_cid_count(struct qed_hwfn *p_hwfn,
                u32 page_sz = p_mgr->clients[ILT_CLI_CDUC].p_size.val;
                u32 cxt_size = CONN_CXT_SIZE(p_hwfn);
                u32 elems_per_page = ILT_PAGE_IN_BYTES(page_sz) / cxt_size;
+               u32 align = elems_per_page * DQ_RANGE_ALIGN;
 
-               p_conn->cid_count = roundup(p_conn->cid_count, elems_per_page);
+               p_conn->cid_count = roundup(p_conn->cid_count, align);
        }
 }
 
index e2a081ceaf520c429b90e1fcc1e2b6cb7d3b10aa..e518f914eab13f52d8f82a8e1a29a5a80a2f2b24 100644 (file)
@@ -2389,9 +2389,8 @@ qed_chain_alloc_sanity_check(struct qed_dev *cdev,
         * size/capacity fields are of a u32 type.
         */
        if ((cnt_type == QED_CHAIN_CNT_TYPE_U16 &&
-            chain_size > 0x10000) ||
-           (cnt_type == QED_CHAIN_CNT_TYPE_U32 &&
-            chain_size > 0x100000000ULL)) {
+            chain_size > ((u32)U16_MAX + 1)) ||
+           (cnt_type == QED_CHAIN_CNT_TYPE_U32 && chain_size > U32_MAX)) {
                DP_NOTICE(cdev,
                          "The actual chain size (0x%llx) is larger than the maximal possible value\n",
                          chain_size);
index 3a44d6b395fac9500841f5ac1bc73b4c11d4d188..098766f7fe88a6e0a131712330cfa3b144c32738 100644 (file)
@@ -190,6 +190,9 @@ qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn,
        p_init->num_sq_pages_in_ring = p_params->num_sq_pages_in_ring;
        p_init->num_r2tq_pages_in_ring = p_params->num_r2tq_pages_in_ring;
        p_init->num_uhq_pages_in_ring = p_params->num_uhq_pages_in_ring;
+       p_init->ooo_enable = p_params->ooo_enable;
+       p_init->ll2_rx_queue_id = p_hwfn->hw_info.resc_start[QED_LL2_QUEUE] +
+                                 p_params->ll2_ooo_queue_id;
        p_init->func_params.log_page_size = p_params->log_page_size;
        val = p_params->num_tasks;
        p_init->func_params.num_tasks = cpu_to_le16(val);
@@ -786,6 +789,23 @@ static void qed_iscsi_release_connection(struct qed_hwfn *p_hwfn,
        spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);
 }
 
+void qed_iscsi_free_connection(struct qed_hwfn *p_hwfn,
+                              struct qed_iscsi_conn *p_conn)
+{
+       qed_chain_free(p_hwfn->cdev, &p_conn->xhq);
+       qed_chain_free(p_hwfn->cdev, &p_conn->uhq);
+       qed_chain_free(p_hwfn->cdev, &p_conn->r2tq);
+       dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+                         sizeof(struct tcp_upload_params),
+                         p_conn->tcp_upload_params_virt_addr,
+                         p_conn->tcp_upload_params_phys_addr);
+       dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+                         sizeof(struct scsi_terminate_extra_params),
+                         p_conn->queue_cnts_virt_addr,
+                         p_conn->queue_cnts_phys_addr);
+       kfree(p_conn);
+}
+
 struct qed_iscsi_info *qed_iscsi_alloc(struct qed_hwfn *p_hwfn)
 {
        struct qed_iscsi_info *p_iscsi_info;
@@ -807,6 +827,17 @@ void qed_iscsi_setup(struct qed_hwfn *p_hwfn,
 void qed_iscsi_free(struct qed_hwfn *p_hwfn,
                    struct qed_iscsi_info *p_iscsi_info)
 {
+       struct qed_iscsi_conn *p_conn = NULL;
+
+       while (!list_empty(&p_hwfn->p_iscsi_info->free_list)) {
+               p_conn = list_first_entry(&p_hwfn->p_iscsi_info->free_list,
+                                         struct qed_iscsi_conn, list_entry);
+               if (p_conn) {
+                       list_del(&p_conn->list_entry);
+                       qed_iscsi_free_connection(p_hwfn, p_conn);
+               }
+       }
+
        kfree(p_iscsi_info);
 }
 
index 9a0b9af10a572f3e3c2a5d086e9e731b040e4d6b..0d3cef409c96d0849c7860e8f03a920b3b8966f1 100644 (file)
@@ -211,6 +211,8 @@ static void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
        /* If need to reuse or there's no replacement buffer, repost this */
        if (rc)
                goto out_post;
+       dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr,
+                        cdev->ll2->rx_size, DMA_FROM_DEVICE);
 
        skb = build_skb(buffer->data, 0);
        if (!skb) {
@@ -474,7 +476,7 @@ qed_ll2_rxq_completion_gsi(struct qed_hwfn *p_hwfn,
 static int qed_ll2_rxq_completion_reg(struct qed_hwfn *p_hwfn,
                                      struct qed_ll2_info *p_ll2_conn,
                                      union core_rx_cqe_union *p_cqe,
-                                     unsigned long lock_flags,
+                                     unsigned long *p_lock_flags,
                                      bool b_last_cqe)
 {
        struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
@@ -495,10 +497,10 @@ static int qed_ll2_rxq_completion_reg(struct qed_hwfn *p_hwfn,
                          "Mismatch between active_descq and the LL2 Rx chain\n");
        list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
 
-       spin_unlock_irqrestore(&p_rx->lock, lock_flags);
+       spin_unlock_irqrestore(&p_rx->lock, *p_lock_flags);
        qed_ll2b_complete_rx_packet(p_hwfn, p_ll2_conn->my_id,
                                    p_pkt, &p_cqe->rx_cqe_fp, b_last_cqe);
-       spin_lock_irqsave(&p_rx->lock, lock_flags);
+       spin_lock_irqsave(&p_rx->lock, *p_lock_flags);
 
        return 0;
 }
@@ -538,7 +540,8 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
                        break;
                case CORE_RX_CQE_TYPE_REGULAR:
                        rc = qed_ll2_rxq_completion_reg(p_hwfn, p_ll2_conn,
-                                                       cqe, flags, b_last_cqe);
+                                                       cqe, &flags,
+                                                       b_last_cqe);
                        break;
                default:
                        rc = -EIO;
@@ -968,7 +971,7 @@ static int qed_ll2_start_ooo(struct qed_dev *cdev,
 {
        struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
        u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
-       struct qed_ll2_conn ll2_info;
+       struct qed_ll2_conn ll2_info = { 0 };
        int rc;
 
        ll2_info.conn_type = QED_LL2_TYPE_ISCSI_OOO;
index 7d731c6cb8923dd927a7bbaafa3a3a97237ba652..378afce58b3f0abd4c2a3bd43f403a50e1a9a1da 100644 (file)
@@ -159,6 +159,8 @@ struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn)
        if (!p_ooo_info->ooo_history.p_cqes)
                goto no_history_mem;
 
+       p_ooo_info->ooo_history.num_of_cqes = QED_MAX_NUM_OOO_HISTORY_ENTRIES;
+
        return p_ooo_info;
 
 no_history_mem:
index 334bcc6df6b2ba90a43da4baf7b44cc5ebfa1bac..50d28261b6b9ea22f42c26be0e9f0e0bed194109 100644 (file)
@@ -2404,7 +2404,7 @@ static void efx_udp_tunnel_del(struct net_device *dev, struct udp_tunnel_info *t
        tnl.type = (u16)efx_tunnel_type;
        tnl.port = ti->port;
 
-       if (efx->type->udp_tnl_add_port)
+       if (efx->type->udp_tnl_del_port)
                (void)efx->type->udp_tnl_del_port(efx, tnl);
 }
 
index 65077c77082a2f042117a0889c2b15099c58eae5..91e9bd7159ab37cab5731fef122345cb59341ba2 100644 (file)
@@ -1535,32 +1535,33 @@ static int smc_close(struct net_device *dev)
  * Ethtool support
  */
 static int
-smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+smc_ethtool_get_link_ksettings(struct net_device *dev,
+                              struct ethtool_link_ksettings *cmd)
 {
        struct smc_local *lp = netdev_priv(dev);
        int ret;
 
-       cmd->maxtxpkt = 1;
-       cmd->maxrxpkt = 1;
-
        if (lp->phy_type != 0) {
                spin_lock_irq(&lp->lock);
-               ret = mii_ethtool_gset(&lp->mii, cmd);
+               ret = mii_ethtool_get_link_ksettings(&lp->mii, cmd);
                spin_unlock_irq(&lp->lock);
        } else {
-               cmd->supported = SUPPORTED_10baseT_Half |
+               u32 supported = SUPPORTED_10baseT_Half |
                                 SUPPORTED_10baseT_Full |
                                 SUPPORTED_TP | SUPPORTED_AUI;
 
                if (lp->ctl_rspeed == 10)
-                       ethtool_cmd_speed_set(cmd, SPEED_10);
+                       cmd->base.speed = SPEED_10;
                else if (lp->ctl_rspeed == 100)
-                       ethtool_cmd_speed_set(cmd, SPEED_100);
+                       cmd->base.speed = SPEED_100;
+
+               cmd->base.autoneg = AUTONEG_DISABLE;
+               cmd->base.port = 0;
+               cmd->base.duplex = lp->tcr_cur_mode & TCR_SWFDUP ?
+                       DUPLEX_FULL : DUPLEX_HALF;
 
-               cmd->autoneg = AUTONEG_DISABLE;
-               cmd->transceiver = XCVR_INTERNAL;
-               cmd->port = 0;
-               cmd->duplex = lp->tcr_cur_mode & TCR_SWFDUP ? DUPLEX_FULL : DUPLEX_HALF;
+               ethtool_convert_legacy_u32_to_link_mode(
+                       cmd->link_modes.supported, supported);
 
                ret = 0;
        }
@@ -1569,24 +1570,26 @@ smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
 }
 
 static int
-smc_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+smc_ethtool_set_link_ksettings(struct net_device *dev,
+                              const struct ethtool_link_ksettings *cmd)
 {
        struct smc_local *lp = netdev_priv(dev);
        int ret;
 
        if (lp->phy_type != 0) {
                spin_lock_irq(&lp->lock);
-               ret = mii_ethtool_sset(&lp->mii, cmd);
+               ret = mii_ethtool_set_link_ksettings(&lp->mii, cmd);
                spin_unlock_irq(&lp->lock);
        } else {
-               if (cmd->autoneg != AUTONEG_DISABLE ||
-                   cmd->speed != SPEED_10 ||
-                   (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) ||
-                   (cmd->port != PORT_TP && cmd->port != PORT_AUI))
+               if (cmd->base.autoneg != AUTONEG_DISABLE ||
+                   cmd->base.speed != SPEED_10 ||
+                   (cmd->base.duplex != DUPLEX_HALF &&
+                    cmd->base.duplex != DUPLEX_FULL) ||
+                   (cmd->base.port != PORT_TP && cmd->base.port != PORT_AUI))
                        return -EINVAL;
 
-//             lp->port = cmd->port;
-               lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL;
+//             lp->port = cmd->base.port;
+               lp->ctl_rfduplx = cmd->base.duplex == DUPLEX_FULL;
 
 //             if (netif_running(dev))
 //                     smc_set_port(dev);
@@ -1744,8 +1747,6 @@ static int smc_ethtool_seteeprom(struct net_device *dev,
 
 
 static const struct ethtool_ops smc_ethtool_ops = {
-       .get_settings   = smc_ethtool_getsettings,
-       .set_settings   = smc_ethtool_setsettings,
        .get_drvinfo    = smc_ethtool_getdrvinfo,
 
        .get_msglevel   = smc_ethtool_getmsglevel,
@@ -1755,6 +1756,8 @@ static const struct ethtool_ops smc_ethtool_ops = {
        .get_eeprom_len = smc_ethtool_geteeprom_len,
        .get_eeprom     = smc_ethtool_geteeprom,
        .set_eeprom     = smc_ethtool_seteeprom,
+       .get_link_ksettings     = smc_ethtool_get_link_ksettings,
+       .set_link_ksettings     = smc_ethtool_set_link_ksettings,
 };
 
 static const struct net_device_ops smc_netdev_ops = {
index 296c8efd0038c8f66f41e9a58e30920462272192..9e631952b86f3d4ddd9108e1fe0db7c96d8363d2 100644 (file)
@@ -74,15 +74,21 @@ config TI_CPSW
          will be called cpsw.
 
 config TI_CPTS
-       tristate "TI Common Platform Time Sync (CPTS) Support"
+       bool "TI Common Platform Time Sync (CPTS) Support"
        depends on TI_CPSW || TI_KEYSTONE_NETCP
-       imply PTP_1588_CLOCK
+       depends on PTP_1588_CLOCK
        ---help---
          This driver supports the Common Platform Time Sync unit of
          the CPSW Ethernet Switch and Keystone 2 1g/10g Switch Subsystem.
          The unit can time stamp PTP UDP/IPv4 and Layer 2 packets, and the
          driver offers a PTP Hardware Clock.
 
+config TI_CPTS_MOD
+       tristate
+       depends on TI_CPTS
+       default y if TI_CPSW=y || TI_KEYSTONE_NETCP=y
+       default m
+
 config TI_KEYSTONE_NETCP
        tristate "TI Keystone NETCP Core Support"
        select TI_CPSW_ALE
index 1e7c10bf87132cda8e9c7ef2afc118ba1725388e..10e6b0ce51baf3115b8c72d40e933f10873186f0 100644 (file)
@@ -12,7 +12,7 @@ obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
 obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
 obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o
 obj-$(CONFIG_TI_CPSW_ALE) += cpsw_ale.o
-obj-$(CONFIG_TI_CPTS) += cpts.o
+obj-$(CONFIG_TI_CPTS_MOD) += cpts.o
 obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
 ti_cpsw-y := cpsw.o
 
index b75d9cdcfb0c415c7abeaa97cebeacbc917e1abd..ae48c809bac9fe13b0a92e086f0a1c6a4cf6feaf 100644 (file)
@@ -45,6 +45,8 @@ MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#define ACPI_MOTHERBOARD_RESOURCE_HID "PNP0C02"
+
 static int fjes_request_irq(struct fjes_adapter *);
 static void fjes_free_irq(struct fjes_adapter *);
 
@@ -78,7 +80,7 @@ static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
 static const struct acpi_device_id fjes_acpi_ids[] = {
-       {"PNP0C02", 0},
+       {ACPI_MOTHERBOARD_RESOURCE_HID, 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
@@ -115,18 +117,17 @@ static struct resource fjes_resource[] = {
        },
 };
 
-static int fjes_acpi_add(struct acpi_device *device)
+static bool is_extended_socket_device(struct acpi_device *device)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
        char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
-       struct platform_device *plat_dev;
        union acpi_object *str;
        acpi_status status;
        int result;
 
        status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
        if (ACPI_FAILURE(status))
-               return -ENODEV;
+               return false;
 
        str = buffer.pointer;
        result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
@@ -136,10 +137,42 @@ static int fjes_acpi_add(struct acpi_device *device)
 
        if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
                kfree(buffer.pointer);
-               return -ENODEV;
+               return false;
        }
        kfree(buffer.pointer);
 
+       return true;
+}
+
+static int acpi_check_extended_socket_status(struct acpi_device *device)
+{
+       unsigned long long sta;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       if (!((sta & ACPI_STA_DEVICE_PRESENT) &&
+             (sta & ACPI_STA_DEVICE_ENABLED) &&
+             (sta & ACPI_STA_DEVICE_UI) &&
+             (sta & ACPI_STA_DEVICE_FUNCTIONING)))
+               return -ENODEV;
+
+       return 0;
+}
+
+static int fjes_acpi_add(struct acpi_device *device)
+{
+       struct platform_device *plat_dev;
+       acpi_status status;
+
+       if (!is_extended_socket_device(device))
+               return -ENODEV;
+
+       if (acpi_check_extended_socket_status(device))
+               return -ENODEV;
+
        status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
                                     fjes_get_acpi_resource, fjes_resource);
        if (ACPI_FAILURE(status))
@@ -1316,7 +1349,7 @@ static void fjes_netdev_setup(struct net_device *netdev)
        netdev->min_mtu = fjes_support_mtu[0];
        netdev->max_mtu = fjes_support_mtu[3];
        netdev->flags |= IFF_BROADCAST;
-       netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
+       netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
 static void fjes_irq_watch_task(struct work_struct *work)
@@ -1473,11 +1506,44 @@ static void fjes_watch_unshare_task(struct work_struct *work)
        }
 }
 
+static acpi_status
+acpi_find_extended_socket_device(acpi_handle obj_handle, u32 level,
+                                void *context, void **return_value)
+{
+       struct acpi_device *device;
+       bool *found = context;
+       int result;
+
+       result = acpi_bus_get_device(obj_handle, &device);
+       if (result)
+               return AE_OK;
+
+       if (strcmp(acpi_device_hid(device), ACPI_MOTHERBOARD_RESOURCE_HID))
+               return AE_OK;
+
+       if (!is_extended_socket_device(device))
+               return AE_OK;
+
+       if (acpi_check_extended_socket_status(device))
+               return AE_OK;
+
+       *found = true;
+       return AE_CTRL_TERMINATE;
+}
+
 /* fjes_init_module - Driver Registration Routine */
 static int __init fjes_init_module(void)
 {
+       bool found = false;
        int result;
 
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+                           acpi_find_extended_socket_device, NULL, &found,
+                           NULL);
+
+       if (!found)
+               return -ENODEV;
+
        pr_info("%s - version %s - %s\n",
                fjes_driver_string, fjes_driver_version, fjes_copyright);
 
index d3e73ac158aee6d3958b18618b85f0180f22abf7..f9f3dba7a58800d9288199b50bec0b85d18cb249 100644 (file)
@@ -700,6 +700,8 @@ struct net_device_context {
 
        u32 tx_checksum_mask;
 
+       u32 tx_send_table[VRSS_SEND_TAB_SIZE];
+
        /* Ethtool settings */
        u8 duplex;
        u32 speed;
@@ -757,7 +759,6 @@ struct netvsc_device {
 
        struct nvsp_message revoke_packet;
 
-       u32 send_table[VRSS_SEND_TAB_SIZE];
        u32 max_chn;
        u32 num_chn;
        spinlock_t sc_lock; /* Protects num_sc_offered variable */
index d35ebd993b385255eaa441fb67272c117e328e7f..8dd0b87703288ccc5f067e495f5b297cde00fba1 100644 (file)
@@ -1136,15 +1136,11 @@ static void netvsc_receive(struct net_device *ndev,
 static void netvsc_send_table(struct hv_device *hdev,
                              struct nvsp_message *nvmsg)
 {
-       struct netvsc_device *nvscdev;
        struct net_device *ndev = hv_get_drvdata(hdev);
+       struct net_device_context *net_device_ctx = netdev_priv(ndev);
        int i;
        u32 count, *tab;
 
-       nvscdev = get_outbound_net_device(hdev);
-       if (!nvscdev)
-               return;
-
        count = nvmsg->msg.v5_msg.send_table.count;
        if (count != VRSS_SEND_TAB_SIZE) {
                netdev_err(ndev, "Received wrong send-table size:%u\n", count);
@@ -1155,7 +1151,7 @@ static void netvsc_send_table(struct hv_device *hdev,
                      nvmsg->msg.v5_msg.send_table.offset);
 
        for (i = 0; i < count; i++)
-               nvscdev->send_table[i] = tab[i];
+               net_device_ctx->tx_send_table[i] = tab[i];
 }
 
 static void netvsc_send_vf(struct net_device_context *net_device_ctx,
@@ -1235,8 +1231,11 @@ void netvsc_channel_cb(void *context)
                return;
 
        net_device = net_device_to_netvsc_device(ndev);
-       if (unlikely(net_device->destroy) &&
-           netvsc_channel_idle(net_device, q_idx))
+       if (unlikely(!net_device))
+               return;
+
+       if (unlikely(net_device->destroy &&
+                    netvsc_channel_idle(net_device, q_idx)))
                return;
 
        /* commit_rd_index() -> hv_signal_on_read() needs this. */
index bc05c895d9589deccd24f1013831036da75e4d1b..5ede87f30463e8211ef2828a8f74d4951c4166a6 100644 (file)
@@ -206,17 +206,15 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
                        void *accel_priv, select_queue_fallback_t fallback)
 {
        struct net_device_context *net_device_ctx = netdev_priv(ndev);
-       struct netvsc_device *nvsc_dev = net_device_ctx->nvdev;
+       unsigned int num_tx_queues = ndev->real_num_tx_queues;
        struct sock *sk = skb->sk;
        int q_idx = sk_tx_queue_get(sk);
 
-       if (q_idx < 0 || skb->ooo_okay ||
-           q_idx >= ndev->real_num_tx_queues) {
+       if (q_idx < 0 || skb->ooo_okay || q_idx >= num_tx_queues) {
                u16 hash = __skb_tx_hash(ndev, skb, VRSS_SEND_TAB_SIZE);
                int new_idx;
 
-               new_idx = nvsc_dev->send_table[hash]
-                       % nvsc_dev->num_chn;
+               new_idx = net_device_ctx->tx_send_table[hash] % num_tx_queues;
 
                if (q_idx != new_idx && sk &&
                    sk_fullsock(sk) && rcu_access_pointer(sk->sk_dst_cache))
@@ -225,9 +223,6 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
                q_idx = new_idx;
        }
 
-       if (unlikely(!nvsc_dev->chan_table[q_idx].channel))
-               q_idx = 0;
-
        return q_idx;
 }
 
index f9d0fa315a47624409cb054e762a6c8b6537a7b6..272b051a019975110aa1d117da993cf18cb98816 100644 (file)
@@ -1883,17 +1883,6 @@ static int m88e1510_probe(struct phy_device *phydev)
        return m88e1510_hwmon_probe(phydev);
 }
 
-static void marvell_remove(struct phy_device *phydev)
-{
-#ifdef CONFIG_HWMON
-
-       struct marvell_priv *priv = phydev->priv;
-
-       if (priv && priv->hwmon_dev)
-               hwmon_device_unregister(priv->hwmon_dev);
-#endif
-}
-
 static struct phy_driver marvell_drivers[] = {
        {
                .phy_id = MARVELL_PHY_ID_88E1101,
@@ -1974,7 +1963,6 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = &m88e1121_probe,
-               .remove = &marvell_remove,
                .config_init = &m88e1121_config_init,
                .config_aneg = &m88e1121_config_aneg,
                .read_status = &marvell_read_status,
@@ -2087,7 +2075,6 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE,
                .flags = PHY_HAS_INTERRUPT,
                .probe = &m88e1510_probe,
-               .remove = &marvell_remove,
                .config_init = &m88e1510_config_init,
                .config_aneg = &m88e1510_config_aneg,
                .read_status = &marvell_read_status,
@@ -2109,7 +2096,6 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = m88e1510_probe,
-               .remove = &marvell_remove,
                .config_init = &marvell_config_init,
                .config_aneg = &m88e1510_config_aneg,
                .read_status = &marvell_read_status,
@@ -2127,7 +2113,6 @@ static struct phy_driver marvell_drivers[] = {
                .phy_id_mask = MARVELL_PHY_ID_MASK,
                .name = "Marvell 88E1545",
                .probe = m88e1510_probe,
-               .remove = &marvell_remove,
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .config_init = &marvell_config_init,
index daec6555f3b10889f786912d286b316a9331480b..5198ccfa347f8b4bfb5ee5e0c69ee12fb44ec681 100644 (file)
@@ -1864,7 +1864,7 @@ static struct phy_driver genphy_driver[] = {
        .phy_id         = 0xffffffff,
        .phy_id_mask    = 0xffffffff,
        .name           = "Generic PHY",
-       .soft_reset     = genphy_soft_reset,
+       .soft_reset     = genphy_no_soft_reset,
        .config_init    = genphy_config_init,
        .features       = PHY_GBIT_FEATURES | SUPPORTED_MII |
                          SUPPORTED_AUI | SUPPORTED_FIBRE |
index 93ffedfa299412f78af2c72fedc991101a52a451..1e2d4f1179da31ed1e458af5e29cc77314f875ad 100644 (file)
@@ -491,13 +491,14 @@ static int ks8995_probe(struct spi_device *spi)
        if (err)
                return err;
 
-       ks->regs_attr.size = ks->chip->regs_size;
        memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr));
+       ks->regs_attr.size = ks->chip->regs_size;
 
        err = ks8995_reset(ks);
        if (err)
                return err;
 
+       sysfs_attr_init(&ks->regs_attr.attr);
        err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr);
        if (err) {
                dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
index 4a24b5d15f5a5dfe770d184533f70f7140d9e145..1b52520715aec6f972626361a6aa93accf809301 100644 (file)
@@ -2072,6 +2072,7 @@ static int team_dev_type_check_change(struct net_device *dev,
 static void team_setup(struct net_device *dev)
 {
        ether_setup(dev);
+       dev->max_mtu = ETH_MAX_MTU;
 
        dev->netdev_ops = &team_netdev_ops;
        dev->ethtool_ops = &team_ethtool_ops;
index dc1b1dd9157c16d1bbd3505751a8782e020ab71a..cc88cd7856f5e5ec4d3e3e309cbefe196c5b27ec 100644 (file)
@@ -822,7 +822,18 @@ static void tun_net_uninit(struct net_device *dev)
 /* Net device open. */
 static int tun_net_open(struct net_device *dev)
 {
+       struct tun_struct *tun = netdev_priv(dev);
+       int i;
+
        netif_tx_start_all_queues(dev);
+
+       for (i = 0; i < tun->numqueues; i++) {
+               struct tun_file *tfile;
+
+               tfile = rtnl_dereference(tun->tfiles[i]);
+               tfile->socket.sk->sk_write_space(tfile->socket.sk);
+       }
+
        return 0;
 }
 
@@ -1103,9 +1114,10 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
        if (!skb_array_empty(&tfile->tx_array))
                mask |= POLLIN | POLLRDNORM;
 
-       if (sock_writeable(sk) ||
-           (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
-            sock_writeable(sk)))
+       if (tun->dev->flags & IFF_UP &&
+           (sock_writeable(sk) ||
+            (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
+             sock_writeable(sk))))
                mask |= POLLOUT | POLLWRNORM;
 
        if (tun->dev->reg_state != NETREG_REGISTERED)
@@ -1919,6 +1931,8 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
                return -EINVAL;
 
        tun->set_features = features;
+       tun->dev->wanted_features &= ~TUN_USER_FEATURES;
+       tun->dev->wanted_features |= features;
        netdev_update_features(tun->dev);
 
        return 0;
@@ -2570,7 +2584,6 @@ static int __init tun_init(void)
        int ret = 0;
 
        pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
-       pr_info("%s\n", DRV_COPYRIGHT);
 
        ret = rtnl_link_register(&tun_link_ops);
        if (ret) {
index 8056745506832867165f03ae0b24c2f1a578d849..156f7f85e4860d682d679df68bfe8cfe2a3d4b3b 100644 (file)
@@ -580,6 +580,10 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* Motorola Mapphone devices with MDM6600 */
+               USB_VENDOR_AND_INTERFACE_INFO(0x22b8, USB_CLASS_VENDOR_SPEC, 0xfb, 0xff),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 2. Combined interface devices matching on class+protocol */
        {       /* Huawei E367 and possibly others in "Windows mode" */
@@ -925,6 +929,8 @@ 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(0x413c, 0x81b3, 8)},    /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
+       {QMI_FIXED_INTF(0x413c, 0x81b6, 8)},    /* Dell Wireless 5811e */
+       {QMI_FIXED_INTF(0x413c, 0x81b6, 10)},   /* Dell Wireless 5811e */
        {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},    /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
        {QMI_FIXED_INTF(0x22de, 0x9061, 3)},    /* WeTelecom WPD-600N */
        {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)},    /* SIMCom 7230E */
index 986243c932ccd6fe19c592805c1c63274f5e5555..0b1b9188625d527e01d098d3ca09389dcfd7bf4d 100644 (file)
@@ -32,7 +32,7 @@
 #define NETNEXT_VERSION                "08"
 
 /* Information for net */
-#define NET_VERSION            "8"
+#define NET_VERSION            "9"
 
 #define DRIVER_VERSION         "v1." NETNEXT_VERSION "." NET_VERSION
 #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
@@ -501,6 +501,8 @@ enum rtl_register_content {
 #define RTL8153_RMS            RTL8153_MAX_PACKET
 #define RTL8152_TX_TIMEOUT     (5 * HZ)
 #define RTL8152_NAPI_WEIGHT    64
+#define rx_reserved_size(x)    ((x) + VLAN_ETH_HLEN + CRC_SIZE + \
+                                sizeof(struct rx_desc) + RX_ALIGN)
 
 /* rtl8152 flags */
 enum rtl8152_flags {
@@ -1362,6 +1364,7 @@ static int alloc_all_mem(struct r8152 *tp)
        spin_lock_init(&tp->rx_lock);
        spin_lock_init(&tp->tx_lock);
        INIT_LIST_HEAD(&tp->tx_free);
+       INIT_LIST_HEAD(&tp->rx_done);
        skb_queue_head_init(&tp->tx_queue);
        skb_queue_head_init(&tp->rx_queue);
 
@@ -2252,8 +2255,7 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp)
 
 static void r8153_set_rx_early_size(struct r8152 *tp)
 {
-       u32 mtu = tp->netdev->mtu;
-       u32 ocp_data = (agg_buf_sz - mtu - VLAN_ETH_HLEN - VLAN_HLEN) / 8;
+       u32 ocp_data = (agg_buf_sz - rx_reserved_size(tp->netdev->mtu)) / 4;
 
        ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data);
 }
@@ -2898,7 +2900,8 @@ static void r8153_first_init(struct r8152 *tp)
 
        rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
 
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
+       ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + CRC_SIZE;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
@@ -2950,7 +2953,8 @@ static void r8153_enter_oob(struct r8152 *tp)
                usleep_range(1000, 2000);
        }
 
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
+       ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + CRC_SIZE;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
        ocp_data &= ~TEREDO_WAKE_MASK;
@@ -4200,8 +4204,14 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
 
        dev->mtu = new_mtu;
 
-       if (netif_running(dev) && netif_carrier_ok(dev))
-               r8153_set_rx_early_size(tp);
+       if (netif_running(dev)) {
+               u32 rms = new_mtu + VLAN_ETH_HLEN + CRC_SIZE;
+
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rms);
+
+               if (netif_carrier_ok(dev))
+                       r8153_set_rx_early_size(tp);
+       }
 
        mutex_unlock(&tp->control);
 
index 22379da63400776ff70994097de6d472232ca908..d6988db1930d6b38db5f932a81c6c64b9c76776a 100644 (file)
@@ -340,6 +340,7 @@ static netdev_tx_t is_ip_tx_frame(struct sk_buff *skb, struct net_device *dev)
 
 static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+       int len = skb->len;
        netdev_tx_t ret = is_ip_tx_frame(skb, dev);
 
        if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
@@ -347,7 +348,7 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
 
                u64_stats_update_begin(&dstats->syncp);
                dstats->tx_pkts++;
-               dstats->tx_bytes += skb->len;
+               dstats->tx_bytes += len;
                u64_stats_update_end(&dstats->syncp);
        } else {
                this_cpu_inc(dev->dstats->tx_drps);
@@ -461,8 +462,10 @@ static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf)
        }
 
        if (rt6_local) {
-               if (rt6_local->rt6i_idev)
+               if (rt6_local->rt6i_idev) {
                        in6_dev_put(rt6_local->rt6i_idev);
+                       rt6_local->rt6i_idev = NULL;
+               }
 
                dst = &rt6_local->dst;
                dev_put(dst->dev);
index e375560cc74e5ffc09553ddab5c6b657fe1cb6f0..bdb6ae16d4a85bf9539199e189011bce104ba51a 100644 (file)
@@ -2976,6 +2976,44 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
        return 0;
 }
 
+static int __vxlan_dev_create(struct net *net, struct net_device *dev,
+                             struct vxlan_config *conf)
+{
+       struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       int err;
+
+       err = vxlan_dev_configure(net, dev, conf, false);
+       if (err)
+               return err;
+
+       dev->ethtool_ops = &vxlan_ethtool_ops;
+
+       /* create an fdb entry for a valid default destination */
+       if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
+               err = vxlan_fdb_create(vxlan, all_zeros_mac,
+                                      &vxlan->default_dst.remote_ip,
+                                      NUD_REACHABLE | NUD_PERMANENT,
+                                      NLM_F_EXCL | NLM_F_CREATE,
+                                      vxlan->cfg.dst_port,
+                                      vxlan->default_dst.remote_vni,
+                                      vxlan->default_dst.remote_vni,
+                                      vxlan->default_dst.remote_ifindex,
+                                      NTF_SELF);
+               if (err)
+                       return err;
+       }
+
+       err = register_netdevice(dev);
+       if (err) {
+               vxlan_fdb_delete_default(vxlan, vxlan->default_dst.remote_vni);
+               return err;
+       }
+
+       list_add(&vxlan->next, &vn->vxlan_list);
+       return 0;
+}
+
 static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
                         struct net_device *dev, struct vxlan_config *conf,
                         bool changelink)
@@ -3172,8 +3210,6 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
 static int vxlan_newlink(struct net *src_net, struct net_device *dev,
                         struct nlattr *tb[], struct nlattr *data[])
 {
-       struct vxlan_net *vn = net_generic(src_net, vxlan_net_id);
-       struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_config conf;
        int err;
 
@@ -3181,36 +3217,7 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
        if (err)
                return err;
 
-       err = vxlan_dev_configure(src_net, dev, &conf, false);
-       if (err)
-               return err;
-
-       dev->ethtool_ops = &vxlan_ethtool_ops;
-
-       /* create an fdb entry for a valid default destination */
-       if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
-               err = vxlan_fdb_create(vxlan, all_zeros_mac,
-                                      &vxlan->default_dst.remote_ip,
-                                      NUD_REACHABLE | NUD_PERMANENT,
-                                      NLM_F_EXCL | NLM_F_CREATE,
-                                      vxlan->cfg.dst_port,
-                                      vxlan->default_dst.remote_vni,
-                                      vxlan->default_dst.remote_vni,
-                                      vxlan->default_dst.remote_ifindex,
-                                      NTF_SELF);
-               if (err)
-                       return err;
-       }
-
-       err = register_netdevice(dev);
-       if (err) {
-               vxlan_fdb_delete_default(vxlan, vxlan->default_dst.remote_vni);
-               return err;
-       }
-
-       list_add(&vxlan->next, &vn->vxlan_list);
-
-       return 0;
+       return __vxlan_dev_create(src_net, dev, &conf);
 }
 
 static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -3440,7 +3447,7 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name,
        if (IS_ERR(dev))
                return dev;
 
-       err = vxlan_dev_configure(net, dev, conf, false);
+       err = __vxlan_dev_create(net, dev, conf);
        if (err < 0) {
                free_netdev(dev);
                return ERR_PTR(err);
index a5045b5279d70a92c827424be3ff7869c6193dc8..6742ae605660454e19406d11f5aff7e84a2527f3 100644 (file)
@@ -381,8 +381,8 @@ static netdev_tx_t ucc_hdlc_tx(struct sk_buff *skb, struct net_device *dev)
        /* set bd status and length */
        bd_status = (bd_status & T_W_S) | T_R_S | T_I_S | T_L_S | T_TC_S;
 
-       iowrite16be(bd_status, &bd->status);
        iowrite16be(skb->len, &bd->length);
+       iowrite16be(bd_status, &bd->status);
 
        /* Move to next BD in the ring */
        if (!(bd_status & T_W_S))
@@ -457,7 +457,7 @@ static int hdlc_rx_done(struct ucc_hdlc_private *priv, int rx_work_limit)
        struct sk_buff *skb;
        hdlc_device *hdlc = dev_to_hdlc(dev);
        struct qe_bd *bd;
-       u32 bd_status;
+       u16 bd_status;
        u16 length, howmany = 0;
        u8 *bdbuffer;
        int i;
index e7f5910a65191f4f013ae53db73d2a77510ae9e8..f8eb66ef2944ea9630237455cae4faf483b4f609 100644 (file)
@@ -467,6 +467,9 @@ int i2400mu_probe(struct usb_interface *iface,
        struct i2400mu *i2400mu;
        struct usb_device *usb_dev = interface_to_usbdev(iface);
 
+       if (iface->cur_altsetting->desc.bNumEndpoints < 4)
+               return -ENODEV;
+
        if (usb_dev->speed != USB_SPEED_HIGH)
                dev_err(dev, "device not connected as high speed\n");
 
index 33fb26833cd0a6b259a131d66972bf7620606f5b..d9f37ee4bfdd3eee9e0a0c11e30165a8b6a7d5ea 100644 (file)
@@ -51,7 +51,7 @@ const struct ath10k_hw_regs qca6174_regs = {
        .rtc_soc_base_address                   = 0x00000800,
        .rtc_wmac_base_address                  = 0x00001000,
        .soc_core_base_address                  = 0x0003a000,
-       .wlan_mac_base_address                  = 0x00020000,
+       .wlan_mac_base_address                  = 0x00010000,
        .ce_wrapper_base_address                = 0x00034000,
        .ce0_base_address                       = 0x00034400,
        .ce1_base_address                       = 0x00034800,
index d37b1695c64eac9096cfe7c11b3ef06764d4626a..6927caecd48e515557d011491463c48a3b1ea95c 100644 (file)
@@ -2319,7 +2319,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
-       /* Called when we need to transmit (a) frame(s) from agg queue */
+       /* Called when we need to transmit (a) frame(s) from agg or dqa queue */
 
        iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
                                          tids, more_data, true);
@@ -2338,7 +2338,8 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
        for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
                struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 
-               if (tid_data->state != IWL_AGG_ON &&
+               if (!iwl_mvm_is_dqa_supported(mvm) &&
+                   tid_data->state != IWL_AGG_ON &&
                    tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
                        continue;
 
index bd1dcc863d8f338df994a9b177d498df2eef49cb..b51a2853cc804a7ad8416423c3cea4554808125d 100644 (file)
@@ -3135,7 +3135,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
                                       struct ieee80211_sta *sta,
                                       enum ieee80211_frame_release_type reason,
                                       u16 cnt, u16 tids, bool more_data,
-                                      bool agg)
+                                      bool single_sta_queue)
 {
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_add_sta_cmd cmd = {
@@ -3155,14 +3155,14 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
        for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT)
                cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]);
 
-       /* If we're releasing frames from aggregation queues then check if the
-        * all queues combined that we're releasing frames from have
+       /* If we're releasing frames from aggregation or dqa queues then check
+        * if all the queues that we're releasing frames from, combined, have:
         *  - more frames than the service period, in which case more_data
         *    needs to be set
         *  - fewer than 'cnt' frames, in which case we need to adjust the
         *    firmware command (but do that unconditionally)
         */
-       if (agg) {
+       if (single_sta_queue) {
                int remaining = cnt;
                int sleep_tx_count;
 
@@ -3172,7 +3172,8 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
                        u16 n_queued;
 
                        tid_data = &mvmsta->tid_data[tid];
-                       if (WARN(tid_data->state != IWL_AGG_ON &&
+                       if (WARN(!iwl_mvm_is_dqa_supported(mvm) &&
+                                tid_data->state != IWL_AGG_ON &&
                                 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA,
                                 "TID %d state is %d\n",
                                 tid, tid_data->state)) {
index 4be34f902278c8bb36521346dfcd7980976e8786..1927ce6077984fff4cde0f767ee97ea42de49761 100644 (file)
@@ -547,7 +547,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
                                       struct ieee80211_sta *sta,
                                       enum ieee80211_frame_release_type reason,
                                       u16 cnt, u16 tids, bool more_data,
-                                      bool agg);
+                                      bool single_sta_queue);
 int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
                      bool drain);
 void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
index dd2b4a30081993823634e18752187c576a656b79..3f37075f4cde3cf21da485cd94b1a3f705abac62 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016        Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -628,8 +629,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
         * values.
         * Note that we don't need to make sure it isn't agg'd, since we're
         * TXing non-sta
+        * For DQA mode - we shouldn't increase it though
         */
-       atomic_inc(&mvm->pending_frames[sta_id]);
+       if (!iwl_mvm_is_dqa_supported(mvm))
+               atomic_inc(&mvm->pending_frames[sta_id]);
 
        return 0;
 }
@@ -1005,11 +1008,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
 
        spin_unlock(&mvmsta->lock);
 
-       /* Increase pending frames count if this isn't AMPDU */
-       if ((iwl_mvm_is_dqa_supported(mvm) &&
-            mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON &&
-            mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) ||
-           (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu))
+       /* Increase pending frames count if this isn't AMPDU or DQA queue */
+       if (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu)
                atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
 
        return 0;
@@ -1079,12 +1079,13 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
        lockdep_assert_held(&mvmsta->lock);
 
        if ((tid_data->state == IWL_AGG_ON ||
-            tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) &&
+            tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA ||
+            iwl_mvm_is_dqa_supported(mvm)) &&
            iwl_mvm_tid_queued(tid_data) == 0) {
                /*
-                * Now that this aggregation queue is empty tell mac80211 so it
-                * knows we no longer have frames buffered for the station on
-                * this TID (for the TIM bitmap calculation.)
+                * Now that this aggregation or DQA queue is empty tell
+                * mac80211 so it knows we no longer have frames buffered for
+                * the station on this TID (for the TIM bitmap calculation.)
                 */
                ieee80211_sta_set_buffered(sta, tid, false);
        }
@@ -1257,7 +1258,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
        u8 skb_freed = 0;
        u16 next_reclaimed, seq_ctl;
        bool is_ndp = false;
-       bool txq_agg = false; /* Is this TXQ aggregated */
 
        __skb_queue_head_init(&skbs);
 
@@ -1283,6 +1283,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                        info->flags |= IEEE80211_TX_STAT_ACK;
                        break;
                case TX_STATUS_FAIL_DEST_PS:
+                       /* In DQA, the FW should have stopped the queue and not
+                        * return this status
+                        */
+                       WARN_ON(iwl_mvm_is_dqa_supported(mvm));
                        info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
                        break;
                default:
@@ -1387,15 +1391,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                        bool send_eosp_ndp = false;
 
                        spin_lock_bh(&mvmsta->lock);
-                       if (iwl_mvm_is_dqa_supported(mvm)) {
-                               enum iwl_mvm_agg_state state;
-
-                               state = mvmsta->tid_data[tid].state;
-                               txq_agg = (state == IWL_AGG_ON ||
-                                       state == IWL_EMPTYING_HW_QUEUE_DELBA);
-                       } else {
-                               txq_agg = txq_id >= mvm->first_agg_queue;
-                       }
 
                        if (!is_ndp) {
                                tid_data->next_reclaimed = next_reclaimed;
@@ -1452,11 +1447,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
         * If the txq is not an AMPDU queue, there is no chance we freed
         * several skbs. Check that out...
         */
-       if (txq_agg)
+       if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue)
                goto out;
 
        /* We can't free more than one frame at once on a shared queue */
-       WARN_ON(!iwl_mvm_is_dqa_supported(mvm) && (skb_freed > 1));
+       WARN_ON(skb_freed > 1);
 
        /* If we have still frames for this STA nothing to do here */
        if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
index 5ebca1d0cfc750969793c26ac5f37e858e897fc4..b62e03d11c2e27c240d02a4e7813958da562aca8 100644 (file)
@@ -57,8 +57,8 @@ MODULE_PARM_DESC(mfg_mode, "manufacturing mode enable:1, disable:0");
  * In case of any errors during inittialization, this function also ensures
  * proper cleanup before exiting.
  */
-static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
-                           void **padapter)
+static int mwifiex_register(void *card, struct device *dev,
+                           struct mwifiex_if_ops *if_ops, void **padapter)
 {
        struct mwifiex_adapter *adapter;
        int i;
@@ -68,6 +68,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
                return -ENOMEM;
 
        *padapter = adapter;
+       adapter->dev = dev;
        adapter->card = card;
 
        /* Save interface specific operations in adapter */
@@ -1568,12 +1569,11 @@ mwifiex_add_card(void *card, struct completion *fw_done,
 {
        struct mwifiex_adapter *adapter;
 
-       if (mwifiex_register(card, if_ops, (void **)&adapter)) {
+       if (mwifiex_register(card, dev, if_ops, (void **)&adapter)) {
                pr_err("%s: software init failed\n", __func__);
                goto err_init_sw;
        }
 
-       adapter->dev = dev;
        mwifiex_probe_of(adapter);
 
        adapter->iface_type = iface_type;
@@ -1718,6 +1718,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter)
        wiphy_unregister(adapter->wiphy);
        wiphy_free(adapter->wiphy);
 
+       if (adapter->irq_wakeup >= 0)
+               device_init_wakeup(adapter->dev, false);
+
        /* Unregister device */
        mwifiex_dbg(adapter, INFO,
                    "info: unregister device\n");
index a0d918094889df6cd9de14046b773d6112b2006b..b8c990d10d6ecb11491cbf5ed345ecbdd7dc0359 100644 (file)
@@ -2739,6 +2739,21 @@ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
        schedule_work(&card->work);
 }
 
+static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+       if (reg->sleep_cookie)
+               mwifiex_pcie_delete_sleep_cookie_buf(adapter);
+
+       mwifiex_pcie_delete_cmdrsp_buf(adapter);
+       mwifiex_pcie_delete_evtbd_ring(adapter);
+       mwifiex_pcie_delete_rxbd_ring(adapter);
+       mwifiex_pcie_delete_txbd_ring(adapter);
+       card->cmdrsp_buf = NULL;
+}
+
 /*
  * This function initializes the PCI-E host memory space, WCB rings, etc.
  *
@@ -2850,13 +2865,6 @@ err_enable_dev:
 
 /*
  * This function cleans up the allocated card buffers.
- *
- * The following are freed by this function -
- *      - TXBD ring buffers
- *      - RXBD ring buffers
- *      - Event BD ring buffers
- *      - Command response ring buffer
- *      - Sleep cookie buffer
  */
 static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
 {
@@ -2875,6 +2883,8 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
                                    "Failed to write driver not-ready signature\n");
        }
 
+       mwifiex_pcie_free_buffers(adapter);
+
        if (pdev) {
                pci_iounmap(pdev, card->pci_mmap);
                pci_iounmap(pdev, card->pci_mmap1);
@@ -3126,10 +3136,7 @@ err_cre_txbd:
        pci_iounmap(pdev, card->pci_mmap1);
 }
 
-/* This function cleans up the PCI-E host memory space.
- * Some code is extracted from mwifiex_unregister_dev()
- *
- */
+/* This function cleans up the PCI-E host memory space. */
 static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
 {
        struct pcie_service_card *card = adapter->card;
@@ -3140,14 +3147,7 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
 
        adapter->seq_num = 0;
 
-       if (reg->sleep_cookie)
-               mwifiex_pcie_delete_sleep_cookie_buf(adapter);
-
-       mwifiex_pcie_delete_cmdrsp_buf(adapter);
-       mwifiex_pcie_delete_evtbd_ring(adapter);
-       mwifiex_pcie_delete_rxbd_ring(adapter);
-       mwifiex_pcie_delete_txbd_ring(adapter);
-       card->cmdrsp_buf = NULL;
+       mwifiex_pcie_free_buffers(adapter);
 }
 
 static struct mwifiex_if_ops pcie_ops = {
index 829b26cd4549a4e07ccdf30ea87d902424ce737b..8397f6c9245158e8b3ff005bc58a419e4250169d 100644 (file)
@@ -165,13 +165,17 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
        struct xenvif_queue *queue = NULL;
-       unsigned int num_queues = vif->num_queues;
+       unsigned int num_queues;
        u16 index;
        struct xenvif_rx_cb *cb;
 
        BUG_ON(skb->dev != dev);
 
-       /* Drop the packet if queues are not set up */
+       /* Drop the packet if queues are not set up.
+        * This handler should be called inside an RCU read section
+        * so we don't need to enter it here explicitly.
+        */
+       num_queues = READ_ONCE(vif->num_queues);
        if (num_queues < 1)
                goto drop;
 
@@ -222,18 +226,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
        struct xenvif_queue *queue = NULL;
+       unsigned int num_queues;
        u64 rx_bytes = 0;
        u64 rx_packets = 0;
        u64 tx_bytes = 0;
        u64 tx_packets = 0;
        unsigned int index;
 
-       spin_lock(&vif->lock);
-       if (vif->queues == NULL)
-               goto out;
+       rcu_read_lock();
+       num_queues = READ_ONCE(vif->num_queues);
 
        /* Aggregate tx and rx stats from each queue */
-       for (index = 0; index < vif->num_queues; ++index) {
+       for (index = 0; index < num_queues; ++index) {
                queue = &vif->queues[index];
                rx_bytes += queue->stats.rx_bytes;
                rx_packets += queue->stats.rx_packets;
@@ -241,8 +245,7 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
                tx_packets += queue->stats.tx_packets;
        }
 
-out:
-       spin_unlock(&vif->lock);
+       rcu_read_unlock();
 
        vif->dev->stats.rx_bytes = rx_bytes;
        vif->dev->stats.rx_packets = rx_packets;
@@ -378,10 +381,13 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,
                                     struct ethtool_stats *stats, u64 * data)
 {
        struct xenvif *vif = netdev_priv(dev);
-       unsigned int num_queues = vif->num_queues;
+       unsigned int num_queues;
        int i;
        unsigned int queue_index;
 
+       rcu_read_lock();
+       num_queues = READ_ONCE(vif->num_queues);
+
        for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) {
                unsigned long accum = 0;
                for (queue_index = 0; queue_index < num_queues; ++queue_index) {
@@ -390,6 +396,8 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,
                }
                data[i] = accum;
        }
+
+       rcu_read_unlock();
 }
 
 static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data)
index f9bcf4a665bcaebc4f33bd28849cef2dadc4f698..602d408fa25e98a4651716b1390d2507bced4605 100644 (file)
@@ -214,7 +214,7 @@ static void xenvif_fatal_tx_err(struct xenvif *vif)
        netdev_err(vif->dev, "fatal error; disabling device\n");
        vif->disabled = true;
        /* Disable the vif from queue 0's kthread */
-       if (vif->queues)
+       if (vif->num_queues)
                xenvif_kick_thread(&vif->queues[0]);
 }
 
index d2d7cd9145b1c259a1f0f11414acca706e67bb7a..a56d3eab35dd650c4acfcda9e981c0220cba9e61 100644 (file)
@@ -495,26 +495,26 @@ static void backend_disconnect(struct backend_info *be)
        struct xenvif *vif = be->vif;
 
        if (vif) {
+               unsigned int num_queues = vif->num_queues;
                unsigned int queue_index;
-               struct xenvif_queue *queues;
 
                xen_unregister_watchers(vif);
 #ifdef CONFIG_DEBUG_FS
                xenvif_debugfs_delif(vif);
 #endif /* CONFIG_DEBUG_FS */
                xenvif_disconnect_data(vif);
-               for (queue_index = 0;
-                    queue_index < vif->num_queues;
-                    ++queue_index)
-                       xenvif_deinit_queue(&vif->queues[queue_index]);
 
-               spin_lock(&vif->lock);
-               queues = vif->queues;
+               /* At this point some of the handlers may still be active
+                * so we need to have additional synchronization here.
+                */
                vif->num_queues = 0;
-               vif->queues = NULL;
-               spin_unlock(&vif->lock);
+               synchronize_net();
 
-               vfree(queues);
+               for (queue_index = 0; queue_index < num_queues; ++queue_index)
+                       xenvif_deinit_queue(&vif->queues[queue_index]);
+
+               vfree(vif->queues);
+               vif->queues = NULL;
 
                xenvif_disconnect_ctrl(vif);
        }
index 779f516e7a4ec405ff919f9b248d21ff0f748b8b..47a479f26e5d7de3605c0263d1a0cdbba1b7e1c1 100644 (file)
@@ -343,8 +343,6 @@ static int __nvme_rdma_init_request(struct nvme_rdma_ctrl *ctrl,
        struct ib_device *ibdev = dev->dev;
        int ret;
 
-       BUG_ON(queue_idx >= ctrl->queue_count);
-
        ret = nvme_rdma_alloc_qe(ibdev, &req->sqe, sizeof(struct nvme_command),
                        DMA_TO_DEVICE);
        if (ret)
@@ -652,8 +650,22 @@ out_free_queues:
 
 static int nvme_rdma_init_io_queues(struct nvme_rdma_ctrl *ctrl)
 {
+       struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
+       unsigned int nr_io_queues;
        int i, ret;
 
+       nr_io_queues = min(opts->nr_io_queues, num_online_cpus());
+       ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
+       if (ret)
+               return ret;
+
+       ctrl->queue_count = nr_io_queues + 1;
+       if (ctrl->queue_count < 2)
+               return 0;
+
+       dev_info(ctrl->ctrl.device,
+               "creating %d I/O queues.\n", nr_io_queues);
+
        for (i = 1; i < ctrl->queue_count; i++) {
                ret = nvme_rdma_init_queue(ctrl, i,
                                           ctrl->ctrl.opts->queue_size);
@@ -1791,20 +1803,8 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
 
 static int nvme_rdma_create_io_queues(struct nvme_rdma_ctrl *ctrl)
 {
-       struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
        int ret;
 
-       ret = nvme_set_queue_count(&ctrl->ctrl, &opts->nr_io_queues);
-       if (ret)
-               return ret;
-
-       ctrl->queue_count = opts->nr_io_queues + 1;
-       if (ctrl->queue_count < 2)
-               return 0;
-
-       dev_info(ctrl->ctrl.device,
-               "creating %d I/O queues.\n", opts->nr_io_queues);
-
        ret = nvme_rdma_init_io_queues(ctrl);
        if (ret)
                return ret;
index 11b0a0a5f661b502d15a22868fe78369ef428627..798653b329b28cb8925cfab4993cc5c6b6afc147 100644 (file)
@@ -425,6 +425,13 @@ void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq,
        ctrl->sqs[qid] = sq;
 }
 
+static void nvmet_confirm_sq(struct percpu_ref *ref)
+{
+       struct nvmet_sq *sq = container_of(ref, struct nvmet_sq, ref);
+
+       complete(&sq->confirm_done);
+}
+
 void nvmet_sq_destroy(struct nvmet_sq *sq)
 {
        /*
@@ -433,7 +440,8 @@ void nvmet_sq_destroy(struct nvmet_sq *sq)
         */
        if (sq->ctrl && sq->ctrl->sqs && sq->ctrl->sqs[0] == sq)
                nvmet_async_events_free(sq->ctrl);
-       percpu_ref_kill(&sq->ref);
+       percpu_ref_kill_and_confirm(&sq->ref, nvmet_confirm_sq);
+       wait_for_completion(&sq->confirm_done);
        wait_for_completion(&sq->free_done);
        percpu_ref_exit(&sq->ref);
 
@@ -461,6 +469,7 @@ int nvmet_sq_init(struct nvmet_sq *sq)
                return ret;
        }
        init_completion(&sq->free_done);
+       init_completion(&sq->confirm_done);
 
        return 0;
 }
index d1f06e7768ff1d7ff6ee787ff6d94eb01576252f..22f7bc6bac7fa77dd48198cde3a31ef60ead531b 100644 (file)
@@ -223,8 +223,6 @@ static void nvme_loop_submit_async_event(struct nvme_ctrl *arg, int aer_idx)
 static int nvme_loop_init_iod(struct nvme_loop_ctrl *ctrl,
                struct nvme_loop_iod *iod, unsigned int queue_idx)
 {
-       BUG_ON(queue_idx >= ctrl->queue_count);
-
        iod->req.cmd = &iod->cmd;
        iod->req.rsp = &iod->rsp;
        iod->queue = &ctrl->queues[queue_idx];
@@ -288,9 +286,9 @@ static struct blk_mq_ops nvme_loop_admin_mq_ops = {
 
 static void nvme_loop_destroy_admin_queue(struct nvme_loop_ctrl *ctrl)
 {
+       nvmet_sq_destroy(&ctrl->queues[0].nvme_sq);
        blk_cleanup_queue(ctrl->ctrl.admin_q);
        blk_mq_free_tag_set(&ctrl->admin_tag_set);
-       nvmet_sq_destroy(&ctrl->queues[0].nvme_sq);
 }
 
 static void nvme_loop_free_ctrl(struct nvme_ctrl *nctrl)
@@ -314,6 +312,43 @@ free_ctrl:
        kfree(ctrl);
 }
 
+static void nvme_loop_destroy_io_queues(struct nvme_loop_ctrl *ctrl)
+{
+       int i;
+
+       for (i = 1; i < ctrl->queue_count; i++)
+               nvmet_sq_destroy(&ctrl->queues[i].nvme_sq);
+}
+
+static int nvme_loop_init_io_queues(struct nvme_loop_ctrl *ctrl)
+{
+       struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
+       unsigned int nr_io_queues;
+       int ret, i;
+
+       nr_io_queues = min(opts->nr_io_queues, num_online_cpus());
+       ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
+       if (ret || !nr_io_queues)
+               return ret;
+
+       dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n", nr_io_queues);
+
+       for (i = 1; i <= nr_io_queues; i++) {
+               ctrl->queues[i].ctrl = ctrl;
+               ret = nvmet_sq_init(&ctrl->queues[i].nvme_sq);
+               if (ret)
+                       goto out_destroy_queues;
+
+               ctrl->queue_count++;
+       }
+
+       return 0;
+
+out_destroy_queues:
+       nvme_loop_destroy_io_queues(ctrl);
+       return ret;
+}
+
 static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
 {
        int error;
@@ -385,17 +420,13 @@ out_free_sq:
 
 static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl)
 {
-       int i;
-
        nvme_stop_keep_alive(&ctrl->ctrl);
 
        if (ctrl->queue_count > 1) {
                nvme_stop_queues(&ctrl->ctrl);
                blk_mq_tagset_busy_iter(&ctrl->tag_set,
                                        nvme_cancel_request, &ctrl->ctrl);
-
-               for (i = 1; i < ctrl->queue_count; i++)
-                       nvmet_sq_destroy(&ctrl->queues[i].nvme_sq);
+               nvme_loop_destroy_io_queues(ctrl);
        }
 
        if (ctrl->ctrl.state == NVME_CTRL_LIVE)
@@ -467,19 +498,14 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)
        if (ret)
                goto out_disable;
 
-       for (i = 1; i <= ctrl->ctrl.opts->nr_io_queues; i++) {
-               ctrl->queues[i].ctrl = ctrl;
-               ret = nvmet_sq_init(&ctrl->queues[i].nvme_sq);
-               if (ret)
-                       goto out_free_queues;
-
-               ctrl->queue_count++;
-       }
+       ret = nvme_loop_init_io_queues(ctrl);
+       if (ret)
+               goto out_destroy_admin;
 
-       for (i = 1; i <= ctrl->ctrl.opts->nr_io_queues; i++) {
+       for (i = 1; i < ctrl->queue_count; i++) {
                ret = nvmf_connect_io_queue(&ctrl->ctrl, i);
                if (ret)
-                       goto out_free_queues;
+                       goto out_destroy_io;
        }
 
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
@@ -492,9 +518,9 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)
 
        return;
 
-out_free_queues:
-       for (i = 1; i < ctrl->queue_count; i++)
-               nvmet_sq_destroy(&ctrl->queues[i].nvme_sq);
+out_destroy_io:
+       nvme_loop_destroy_io_queues(ctrl);
+out_destroy_admin:
        nvme_loop_destroy_admin_queue(ctrl);
 out_disable:
        dev_warn(ctrl->ctrl.device, "Removing after reset failure\n");
@@ -533,25 +559,12 @@ static const struct nvme_ctrl_ops nvme_loop_ctrl_ops = {
 
 static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
 {
-       struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
        int ret, i;
 
-       ret = nvme_set_queue_count(&ctrl->ctrl, &opts->nr_io_queues);
-       if (ret || !opts->nr_io_queues)
+       ret = nvme_loop_init_io_queues(ctrl);
+       if (ret)
                return ret;
 
-       dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n",
-               opts->nr_io_queues);
-
-       for (i = 1; i <= opts->nr_io_queues; i++) {
-               ctrl->queues[i].ctrl = ctrl;
-               ret = nvmet_sq_init(&ctrl->queues[i].nvme_sq);
-               if (ret)
-                       goto out_destroy_queues;
-
-               ctrl->queue_count++;
-       }
-
        memset(&ctrl->tag_set, 0, sizeof(ctrl->tag_set));
        ctrl->tag_set.ops = &nvme_loop_mq_ops;
        ctrl->tag_set.queue_depth = ctrl->ctrl.opts->queue_size;
@@ -575,7 +588,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
                goto out_free_tagset;
        }
 
-       for (i = 1; i <= opts->nr_io_queues; i++) {
+       for (i = 1; i < ctrl->queue_count; i++) {
                ret = nvmf_connect_io_queue(&ctrl->ctrl, i);
                if (ret)
                        goto out_cleanup_connect_q;
@@ -588,8 +601,7 @@ out_cleanup_connect_q:
 out_free_tagset:
        blk_mq_free_tag_set(&ctrl->tag_set);
 out_destroy_queues:
-       for (i = 1; i < ctrl->queue_count; i++)
-               nvmet_sq_destroy(&ctrl->queues[i].nvme_sq);
+       nvme_loop_destroy_io_queues(ctrl);
        return ret;
 }
 
index 1370eee0a3c0f6295722d22e0c103a2f6cece47b..f7ff15f17ca97d65161cdb6a164e62deff339916 100644 (file)
@@ -73,6 +73,7 @@ struct nvmet_sq {
        u16                     qid;
        u16                     size;
        struct completion       free_done;
+       struct completion       confirm_done;
 };
 
 /**
index 9aa1da3778b3ac1d2262bfe9b845b65b9cd942d9..ecc4fe8625612442ded6a554e762d029b908c8dc 100644 (file)
@@ -703,11 +703,6 @@ static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue,
 {
        u16 status;
 
-       cmd->queue = queue;
-       cmd->n_rdma = 0;
-       cmd->req.port = queue->port;
-
-
        ib_dma_sync_single_for_cpu(queue->dev->device,
                cmd->cmd->sge[0].addr, cmd->cmd->sge[0].length,
                DMA_FROM_DEVICE);
@@ -760,9 +755,12 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 
        cmd->queue = queue;
        rsp = nvmet_rdma_get_rsp(queue);
+       rsp->queue = queue;
        rsp->cmd = cmd;
        rsp->flags = 0;
        rsp->req.cmd = cmd->nvme_cmd;
+       rsp->req.port = queue->port;
+       rsp->n_rdma = 0;
 
        if (unlikely(queue->state != NVMET_RDMA_Q_LIVE)) {
                unsigned long flags;
index dc5277ad1b5a7a5a7b27a7329f0f6382587e6050..005cadb7a3f8e9076700bf24d280383a0d321c85 100644 (file)
@@ -449,6 +449,7 @@ config PHY_QCOM_UFS
 config PHY_QCOM_USB_HS
        tristate "Qualcomm USB HS PHY module"
        depends on USB_ULPI_BUS
+       depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
        select GENERIC_PHY
        help
          Support for the USB high-speed ULPI compliant phy on Qualcomm
@@ -510,12 +511,4 @@ config PHY_MESON8B_USB2
          and GXBB SoCs.
          If unsure, say N.
 
-config PHY_NSP_USB3
-       tristate "Broadcom NorthStar plus USB3 PHY driver"
-       depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
-       select GENERIC_PHY
-       default ARCH_BCM_NSP
-       help
-         Enable this to support the Broadcom Northstar plus USB3 PHY.
-         If unsure, say N.
 endmenu
index e7b0feb1e125a58c25fb96e784deae62bfb891e7..dd8f3b5d2918cd91bd48592b6771ca539321b086 100644 (file)
@@ -62,4 +62,3 @@ obj-$(CONFIG_PHY_CYGNUS_PCIE)         += phy-bcm-cygnus-pcie.o
 obj-$(CONFIG_ARCH_TEGRA) += tegra/
 obj-$(CONFIG_PHY_NS2_PCIE)             += phy-bcm-ns2-pcie.o
 obj-$(CONFIG_PHY_MESON8B_USB2)         += phy-meson8b-usb2.o
-obj-$(CONFIG_PHY_NSP_USB3)             += phy-bcm-nsp-usb3.o
diff --git a/drivers/phy/phy-bcm-nsp-usb3.c b/drivers/phy/phy-bcm-nsp-usb3.c
deleted file mode 100644 (file)
index 49024ea..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 Broadcom
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mdio.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-#define NSP_USB3_RST_CTRL_OFFSET       0x3f8
-
-/* mdio reg access */
-#define NSP_USB3_PHY_BASE_ADDR_REG     0x1f
-
-#define NSP_USB3_PHY_PLL30_BLOCK       0x8000
-#define NSP_USB3_PLL_CONTROL           0x01
-#define NSP_USB3_PLLA_CONTROL0         0x0a
-#define NSP_USB3_PLLA_CONTROL1         0x0b
-
-#define NSP_USB3_PHY_TX_PMD_BLOCK      0x8040
-#define NSP_USB3_TX_PMD_CONTROL1       0x01
-
-#define NSP_USB3_PHY_PIPE_BLOCK                0x8060
-#define NSP_USB3_LFPS_CMP              0x02
-#define NSP_USB3_LFPS_DEGLITCH         0x03
-
-struct nsp_usb3_phy {
-       struct regmap *usb3_ctrl;
-       struct phy *phy;
-       struct mdio_device *mdiodev;
-};
-
-static int nsp_usb3_phy_init(struct phy *phy)
-{
-       struct nsp_usb3_phy *iphy = phy_get_drvdata(phy);
-       struct mii_bus *bus = iphy->mdiodev->bus;
-       int addr = iphy->mdiodev->addr;
-       u32 data;
-       int rc;
-
-       rc = regmap_read(iphy->usb3_ctrl, 0, &data);
-       if (rc)
-               return rc;
-       data |= 1;
-       rc = regmap_write(iphy->usb3_ctrl, 0, data);
-       if (rc)
-               return rc;
-
-       rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 1);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
-                          NSP_USB3_PHY_PLL30_BLOCK);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x1000);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL0, 0x6400);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0xc000);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0x8000);
-       if (rc)
-               return rc;
-
-       rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 0);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x9000);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
-                          NSP_USB3_PHY_PIPE_BLOCK);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_CMP, 0xf30d);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_DEGLITCH, 0x6302);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
-                          NSP_USB3_PHY_TX_PMD_BLOCK);
-       if (rc)
-               return rc;
-
-       rc = mdiobus_write(bus, addr, NSP_USB3_TX_PMD_CONTROL1, 0x1003);
-
-       return rc;
-}
-
-static struct phy_ops nsp_usb3_phy_ops = {
-       .init   = nsp_usb3_phy_init,
-       .owner  = THIS_MODULE,
-};
-
-static int nsp_usb3_phy_probe(struct mdio_device *mdiodev)
-{
-       struct device *dev = &mdiodev->dev;
-       struct phy_provider *provider;
-       struct nsp_usb3_phy *iphy;
-
-       iphy = devm_kzalloc(dev, sizeof(*iphy), GFP_KERNEL);
-       if (!iphy)
-               return -ENOMEM;
-       iphy->mdiodev = mdiodev;
-
-       iphy->usb3_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                                "usb3-ctrl-syscon");
-       if (IS_ERR(iphy->usb3_ctrl))
-               return PTR_ERR(iphy->usb3_ctrl);
-
-       iphy->phy = devm_phy_create(dev, dev->of_node, &nsp_usb3_phy_ops);
-       if (IS_ERR(iphy->phy)) {
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(iphy->phy);
-       }
-
-       phy_set_drvdata(iphy->phy, iphy);
-
-       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(provider)) {
-               dev_err(dev, "could not register PHY provider\n");
-               return PTR_ERR(provider);
-       }
-
-       return 0;
-}
-
-static const struct of_device_id nsp_usb3_phy_of_match[] = {
-       {.compatible = "brcm,nsp-usb3-phy",},
-       { /* sentinel */ }
-};
-
-static struct mdio_driver nsp_usb3_phy_driver = {
-       .mdiodrv = {
-               .driver = {
-                       .name = "nsp-usb3-phy",
-                       .of_match_table = nsp_usb3_phy_of_match,
-               },
-       },
-       .probe = nsp_usb3_phy_probe,
-};
-
-mdio_module_driver(nsp_usb3_phy_driver);
-
-MODULE_DESCRIPTION("Broadcom NSP USB3 PHY driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com");
index 4f60b83641d5952d55edd37137283114ea9ba836..60baf25d98e25eb3e716979a54223dd3d03e198d 100644 (file)
@@ -254,8 +254,8 @@ static int exynos_pcie_phy_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        exynos_phy->blk_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(exynos_phy->phy_base))
-               return PTR_ERR(exynos_phy->phy_base);
+       if (IS_ERR(exynos_phy->blk_base))
+               return PTR_ERR(exynos_phy->blk_base);
 
        exynos_phy->drv_data = drv_data;
 
index 5be4783e40d4c9e9ca547d89d5faa6c1437f927a..dea98ffb6f606a6079f40607c8f5476c7a738f7d 100644 (file)
@@ -103,15 +103,6 @@ static struct quirk_entry quirk_asus_x200ca = {
        .wapf = 2,
 };
 
-static struct quirk_entry quirk_no_rfkill = {
-       .no_rfkill = true,
-};
-
-static struct quirk_entry quirk_no_rfkill_wapf4 = {
-       .wapf = 4,
-       .no_rfkill = true,
-};
-
 static struct quirk_entry quirk_asus_ux303ub = {
        .wmi_backlight_native = true,
 };
@@ -194,7 +185,7 @@ static const struct dmi_system_id asus_quirks[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
                        DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"),
                },
-               .driver_data = &quirk_no_rfkill_wapf4,
+               .driver_data = &quirk_asus_wapf4,
        },
        {
                .callback = dmi_matched,
@@ -203,7 +194,7 @@ static const struct dmi_system_id asus_quirks[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
                        DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"),
                },
-               .driver_data = &quirk_no_rfkill_wapf4,
+               .driver_data = &quirk_asus_wapf4,
        },
        {
                .callback = dmi_matched,
@@ -367,42 +358,6 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_x200ca,
        },
-       {
-               .callback = dmi_matched,
-               .ident = "ASUSTeK COMPUTER INC. X555UB",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X555UB"),
-               },
-               .driver_data = &quirk_no_rfkill,
-       },
-       {
-               .callback = dmi_matched,
-               .ident = "ASUSTeK COMPUTER INC. N552VW",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N552VW"),
-               },
-               .driver_data = &quirk_no_rfkill,
-       },
-       {
-               .callback = dmi_matched,
-               .ident = "ASUSTeK COMPUTER INC. U303LB",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "U303LB"),
-               },
-               .driver_data = &quirk_no_rfkill,
-       },
-       {
-               .callback = dmi_matched,
-               .ident = "ASUSTeK COMPUTER INC. Z550MA",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Z550MA"),
-               },
-               .driver_data = &quirk_no_rfkill,
-       },
        {
                .callback = dmi_matched,
                .ident = "ASUSTeK COMPUTER INC. UX303UB",
index 43cb680adbb42045aaeea332220460440180215a..8fe5890bf539f4f2eb722139f4c56a3065403e92 100644 (file)
@@ -159,6 +159,8 @@ MODULE_LICENSE("GPL");
 #define USB_INTEL_XUSB2PR              0xD0
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI  0x9c31
 
+static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
+
 struct bios_args {
        u32 arg0;
        u32 arg1;
@@ -2051,6 +2053,16 @@ static int asus_wmi_fan_init(struct asus_wmi *asus)
        return 0;
 }
 
+static bool ashs_present(void)
+{
+       int i = 0;
+       while (ashs_ids[i]) {
+               if (acpi_dev_found(ashs_ids[i++]))
+                       return true;
+       }
+       return false;
+}
+
 /*
  * WMI Driver
  */
@@ -2095,7 +2107,11 @@ static int asus_wmi_add(struct platform_device *pdev)
        if (err)
                goto fail_leds;
 
-       if (!asus->driver->quirks->no_rfkill) {
+       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
+       if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
+               asus->driver->wlan_ctrl_by_user = 1;
+
+       if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) {
                err = asus_wmi_rfkill_init(asus);
                if (err)
                        goto fail_rfkill;
@@ -2134,10 +2150,6 @@ static int asus_wmi_add(struct platform_device *pdev)
        if (err)
                goto fail_debugfs;
 
-       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
-       if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
-               asus->driver->wlan_ctrl_by_user = 1;
-
        return 0;
 
 fail_debugfs:
index fdff626c3b51b039f3b63473a6cf333d04fda819..c9589d9342bbf8f883c49abbcd7cebf9a23c608e 100644 (file)
@@ -39,7 +39,6 @@ struct key_entry;
 struct asus_wmi;
 
 struct quirk_entry {
-       bool no_rfkill;
        bool hotplug_wireless;
        bool scalar_panel_brightness;
        bool store_backlight_power;
index 2b218b1d13e55dc985a2ca27e44b6a6ddf905141..e12cc3504d48799b447e636e21c2c6c440fc5827 100644 (file)
 
 #define FUJITSU_LCD_N_LEVELS 8
 
-#define ACPI_FUJITSU_CLASS              "fujitsu"
-#define ACPI_FUJITSU_HID                "FUJ02B1"
-#define ACPI_FUJITSU_DRIVER_NAME       "Fujitsu laptop FUJ02B1 ACPI brightness driver"
-#define ACPI_FUJITSU_DEVICE_NAME        "Fujitsu FUJ02B1"
-#define ACPI_FUJITSU_HOTKEY_HID        "FUJ02E3"
-#define ACPI_FUJITSU_HOTKEY_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
-#define ACPI_FUJITSU_HOTKEY_DEVICE_NAME "Fujitsu FUJ02E3"
+#define ACPI_FUJITSU_CLASS             "fujitsu"
+#define ACPI_FUJITSU_BL_HID            "FUJ02B1"
+#define ACPI_FUJITSU_BL_DRIVER_NAME    "Fujitsu laptop FUJ02B1 ACPI brightness driver"
+#define ACPI_FUJITSU_BL_DEVICE_NAME    "Fujitsu FUJ02B1"
+#define ACPI_FUJITSU_LAPTOP_HID                "FUJ02E3"
+#define ACPI_FUJITSU_LAPTOP_DRIVER_NAME        "Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
+#define ACPI_FUJITSU_LAPTOP_DEVICE_NAME        "Fujitsu FUJ02E3"
 
 #define ACPI_FUJITSU_NOTIFY_CODE1     0x80
 
 /* FUNC interface - command values */
-#define FUNC_RFKILL    0x1000
+#define FUNC_FLAGS     0x1000
 #define FUNC_LEDS      0x1001
 #define FUNC_BUTTONS   0x1002
 #define FUNC_BACKLIGHT  0x1004
 /* FUNC interface - responses */
 #define UNSUPPORTED_CMD 0x80000000
 
+/* FUNC interface - status flags */
+#define FLAG_RFKILL    0x020
+#define FLAG_LID       0x100
+#define FLAG_DOCK      0x200
+
 #if IS_ENABLED(CONFIG_LEDS_CLASS)
 /* FUNC interface - LED control */
 #define FUNC_LED_OFF   0x1
 #endif
 
 /* Device controlling the backlight and associated keys */
-struct fujitsu_t {
+struct fujitsu_bl {
        acpi_handle acpi_handle;
        struct acpi_device *dev;
        struct input_dev *input;
@@ -150,12 +155,12 @@ struct fujitsu_t {
        unsigned int brightness_level;
 };
 
-static struct fujitsu_t *fujitsu;
+static struct fujitsu_bl *fujitsu_bl;
 static int use_alt_lcd_levels = -1;
 static int disable_brightness_adjust = -1;
 
-/* Device used to access other hotkeys on the laptop */
-struct fujitsu_hotkey_t {
+/* Device used to access hotkeys and other features on the laptop */
+struct fujitsu_laptop {
        acpi_handle acpi_handle;
        struct acpi_device *dev;
        struct input_dev *input;
@@ -163,17 +168,15 @@ struct fujitsu_hotkey_t {
        struct platform_device *pf_device;
        struct kfifo fifo;
        spinlock_t fifo_lock;
-       int rfkill_supported;
-       int rfkill_state;
+       int flags_supported;
+       int flags_state;
        int logolamp_registered;
        int kblamps_registered;
        int radio_led_registered;
        int eco_led_registered;
 };
 
-static struct fujitsu_hotkey_t *fujitsu_hotkey;
-
-static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event);
+static struct fujitsu_laptop *fujitsu_laptop;
 
 #if IS_ENABLED(CONFIG_LEDS_CLASS)
 static enum led_brightness logolamp_get(struct led_classdev *cdev);
@@ -222,8 +225,6 @@ static struct led_classdev eco_led = {
 static u32 dbg_level = 0x03;
 #endif
 
-static void acpi_fujitsu_notify(struct acpi_device *device, u32 event);
-
 /* Fujitsu ACPI interface function */
 
 static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
@@ -239,7 +240,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
        unsigned long long value;
        acpi_handle handle = NULL;
 
-       status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle);
+       status = acpi_get_handle(fujitsu_laptop->acpi_handle, "FUNC", &handle);
        if (ACPI_FAILURE(status)) {
                vdbg_printk(FUJLAPTOP_DBG_ERROR,
                                "FUNC interface is not present\n");
@@ -300,9 +301,9 @@ static int radio_led_set(struct led_classdev *cdev,
                                enum led_brightness brightness)
 {
        if (brightness >= LED_FULL)
-               return call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON);
+               return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, RADIO_LED_ON);
        else
-               return call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0);
+               return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 0x0);
 }
 
 static int eco_led_set(struct led_classdev *cdev,
@@ -346,7 +347,7 @@ static enum led_brightness radio_led_get(struct led_classdev *cdev)
 {
        enum led_brightness brightness = LED_OFF;
 
-       if (call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0) & RADIO_LED_ON)
+       if (call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON)
                brightness = LED_FULL;
 
        return brightness;
@@ -373,10 +374,10 @@ static int set_lcd_level(int level)
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
                    level);
 
-       if (level < 0 || level >= fujitsu->max_brightness)
+       if (level < 0 || level >= fujitsu_bl->max_brightness)
                return -EINVAL;
 
-       status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
+       status = acpi_get_handle(fujitsu_bl->acpi_handle, "SBLL", &handle);
        if (ACPI_FAILURE(status)) {
                vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n");
                return -ENODEV;
@@ -398,10 +399,10 @@ static int set_lcd_level_alt(int level)
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
                    level);
 
-       if (level < 0 || level >= fujitsu->max_brightness)
+       if (level < 0 || level >= fujitsu_bl->max_brightness)
                return -EINVAL;
 
-       status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle);
+       status = acpi_get_handle(fujitsu_bl->acpi_handle, "SBL2", &handle);
        if (ACPI_FAILURE(status)) {
                vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n");
                return -ENODEV;
@@ -421,19 +422,19 @@ static int get_lcd_level(void)
 
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n");
 
-       status =
-           acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
+       status = acpi_evaluate_integer(fujitsu_bl->acpi_handle, "GBLL", NULL,
+                                      &state);
        if (ACPI_FAILURE(status))
                return 0;
 
-       fujitsu->brightness_level = state & 0x0fffffff;
+       fujitsu_bl->brightness_level = state & 0x0fffffff;
 
        if (state & 0x80000000)
-               fujitsu->brightness_changed = 1;
+               fujitsu_bl->brightness_changed = 1;
        else
-               fujitsu->brightness_changed = 0;
+               fujitsu_bl->brightness_changed = 0;
 
-       return fujitsu->brightness_level;
+       return fujitsu_bl->brightness_level;
 }
 
 static int get_max_brightness(void)
@@ -443,14 +444,14 @@ static int get_max_brightness(void)
 
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n");
 
-       status =
-           acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state);
+       status = acpi_evaluate_integer(fujitsu_bl->acpi_handle, "RBLL", NULL,
+                                      &state);
        if (ACPI_FAILURE(status))
                return -1;
 
-       fujitsu->max_brightness = state;
+       fujitsu_bl->max_brightness = state;
 
-       return fujitsu->max_brightness;
+       return fujitsu_bl->max_brightness;
 }
 
 /* Backlight device stuff */
@@ -483,7 +484,7 @@ static int bl_update_status(struct backlight_device *b)
        return ret;
 }
 
-static const struct backlight_ops fujitsubl_ops = {
+static const struct backlight_ops fujitsu_bl_ops = {
        .get_brightness = bl_get_brightness,
        .update_status = bl_update_status,
 };
@@ -511,7 +512,7 @@ show_brightness_changed(struct device *dev,
 
        int ret;
 
-       ret = fujitsu->brightness_changed;
+       ret = fujitsu_bl->brightness_changed;
        if (ret < 0)
                return ret;
 
@@ -539,7 +540,7 @@ static ssize_t store_lcd_level(struct device *dev,
        int level, ret;
 
        if (sscanf(buf, "%i", &level) != 1
-           || (level < 0 || level >= fujitsu->max_brightness))
+           || (level < 0 || level >= fujitsu_bl->max_brightness))
                return -EINVAL;
 
        if (use_alt_lcd_levels)
@@ -567,9 +568,9 @@ static ssize_t
 show_lid_state(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       if (!(fujitsu_hotkey->rfkill_supported & 0x100))
+       if (!(fujitsu_laptop->flags_supported & FLAG_LID))
                return sprintf(buf, "unknown\n");
-       if (fujitsu_hotkey->rfkill_state & 0x100)
+       if (fujitsu_laptop->flags_state & FLAG_LID)
                return sprintf(buf, "open\n");
        else
                return sprintf(buf, "closed\n");
@@ -579,9 +580,9 @@ static ssize_t
 show_dock_state(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       if (!(fujitsu_hotkey->rfkill_supported & 0x200))
+       if (!(fujitsu_laptop->flags_supported & FLAG_DOCK))
                return sprintf(buf, "unknown\n");
-       if (fujitsu_hotkey->rfkill_state & 0x200)
+       if (fujitsu_laptop->flags_state & FLAG_DOCK)
                return sprintf(buf, "docked\n");
        else
                return sprintf(buf, "undocked\n");
@@ -591,9 +592,9 @@ static ssize_t
 show_radios_state(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       if (!(fujitsu_hotkey->rfkill_supported & 0x20))
+       if (!(fujitsu_laptop->flags_supported & FLAG_RFKILL))
                return sprintf(buf, "unknown\n");
-       if (fujitsu_hotkey->rfkill_state & 0x20)
+       if (fujitsu_laptop->flags_state & FLAG_RFKILL)
                return sprintf(buf, "on\n");
        else
                return sprintf(buf, "killed\n");
@@ -607,7 +608,7 @@ static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store);
 static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store);
 static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store);
 
-static struct attribute *fujitsupf_attributes[] = {
+static struct attribute *fujitsu_pf_attributes[] = {
        &dev_attr_brightness_changed.attr,
        &dev_attr_max_brightness.attr,
        &dev_attr_lcd_level.attr,
@@ -617,11 +618,11 @@ static struct attribute *fujitsupf_attributes[] = {
        NULL
 };
 
-static struct attribute_group fujitsupf_attribute_group = {
-       .attrs = fujitsupf_attributes
+static struct attribute_group fujitsu_pf_attribute_group = {
+       .attrs = fujitsu_pf_attributes
 };
 
-static struct platform_driver fujitsupf_driver = {
+static struct platform_driver fujitsu_pf_driver = {
        .driver = {
                   .name = "fujitsu-laptop",
                   }
@@ -630,39 +631,30 @@ static struct platform_driver fujitsupf_driver = {
 static void __init dmi_check_cb_common(const struct dmi_system_id *id)
 {
        pr_info("Identified laptop model '%s'\n", id->ident);
-       if (use_alt_lcd_levels == -1) {
-               if (acpi_has_method(NULL,
-                               "\\_SB.PCI0.LPCB.FJEX.SBL2"))
-                       use_alt_lcd_levels = 1;
-               else
-                       use_alt_lcd_levels = 0;
-               vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as "
-                       "%i\n", use_alt_lcd_levels);
-       }
 }
 
 static int __init dmi_check_cb_s6410(const struct dmi_system_id *id)
 {
        dmi_check_cb_common(id);
-       fujitsu->keycode1 = KEY_SCREENLOCK;     /* "Lock" */
-       fujitsu->keycode2 = KEY_HELP;   /* "Mobility Center" */
+       fujitsu_bl->keycode1 = KEY_SCREENLOCK;  /* "Lock" */
+       fujitsu_bl->keycode2 = KEY_HELP;        /* "Mobility Center" */
        return 1;
 }
 
 static int __init dmi_check_cb_s6420(const struct dmi_system_id *id)
 {
        dmi_check_cb_common(id);
-       fujitsu->keycode1 = KEY_SCREENLOCK;     /* "Lock" */
-       fujitsu->keycode2 = KEY_HELP;   /* "Mobility Center" */
+       fujitsu_bl->keycode1 = KEY_SCREENLOCK;  /* "Lock" */
+       fujitsu_bl->keycode2 = KEY_HELP;        /* "Mobility Center" */
        return 1;
 }
 
 static int __init dmi_check_cb_p8010(const struct dmi_system_id *id)
 {
        dmi_check_cb_common(id);
-       fujitsu->keycode1 = KEY_HELP;   /* "Support" */
-       fujitsu->keycode3 = KEY_SWITCHVIDEOMODE;        /* "Presentation" */
-       fujitsu->keycode4 = KEY_WWW;    /* "Internet" */
+       fujitsu_bl->keycode1 = KEY_HELP;                /* "Support" */
+       fujitsu_bl->keycode3 = KEY_SWITCHVIDEOMODE;     /* "Presentation" */
+       fujitsu_bl->keycode4 = KEY_WWW;                 /* "Internet" */
        return 1;
 }
 
@@ -693,7 +685,7 @@ static const struct dmi_system_id fujitsu_dmi_table[] __initconst = {
 
 /* ACPI device for LCD brightness control */
 
-static int acpi_fujitsu_add(struct acpi_device *device)
+static int acpi_fujitsu_bl_add(struct acpi_device *device)
 {
        int state = 0;
        struct input_dev *input;
@@ -702,22 +694,22 @@ static int acpi_fujitsu_add(struct acpi_device *device)
        if (!device)
                return -EINVAL;
 
-       fujitsu->acpi_handle = device->handle;
-       sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME);
+       fujitsu_bl->acpi_handle = device->handle;
+       sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_BL_DEVICE_NAME);
        sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
-       device->driver_data = fujitsu;
+       device->driver_data = fujitsu_bl;
 
-       fujitsu->input = input = input_allocate_device();
+       fujitsu_bl->input = input = input_allocate_device();
        if (!input) {
                error = -ENOMEM;
                goto err_stop;
        }
 
-       snprintf(fujitsu->phys, sizeof(fujitsu->phys),
+       snprintf(fujitsu_bl->phys, sizeof(fujitsu_bl->phys),
                 "%s/video/input0", acpi_device_hid(device));
 
        input->name = acpi_device_name(device);
-       input->phys = fujitsu->phys;
+       input->phys = fujitsu_bl->phys;
        input->id.bustype = BUS_HOST;
        input->id.product = 0x06;
        input->dev.parent = &device->dev;
@@ -730,7 +722,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
        if (error)
                goto err_free_input_dev;
 
-       error = acpi_bus_update_power(fujitsu->acpi_handle, &state);
+       error = acpi_bus_update_power(fujitsu_bl->acpi_handle, &state);
        if (error) {
                pr_err("Error reading power state\n");
                goto err_unregister_input_dev;
@@ -740,7 +732,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
               acpi_device_name(device), acpi_device_bid(device),
               !device->power.state ? "on" : "off");
 
-       fujitsu->dev = device;
+       fujitsu_bl->dev = device;
 
        if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
                vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
@@ -750,6 +742,15 @@ static int acpi_fujitsu_add(struct acpi_device *device)
                        pr_err("_INI Method failed\n");
        }
 
+       if (use_alt_lcd_levels == -1) {
+               if (acpi_has_method(NULL, "\\_SB.PCI0.LPCB.FJEX.SBL2"))
+                       use_alt_lcd_levels = 1;
+               else
+                       use_alt_lcd_levels = 0;
+               vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as %i\n",
+                           use_alt_lcd_levels);
+       }
+
        /* do config (detect defaults) */
        use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
        disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
@@ -758,7 +759,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
                    use_alt_lcd_levels, disable_brightness_adjust);
 
        if (get_max_brightness() <= 0)
-               fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS;
+               fujitsu_bl->max_brightness = FUJITSU_LCD_N_LEVELS;
        get_lcd_level();
 
        return 0;
@@ -772,38 +773,38 @@ err_stop:
        return error;
 }
 
-static int acpi_fujitsu_remove(struct acpi_device *device)
+static int acpi_fujitsu_bl_remove(struct acpi_device *device)
 {
-       struct fujitsu_t *fujitsu = acpi_driver_data(device);
-       struct input_dev *input = fujitsu->input;
+       struct fujitsu_bl *fujitsu_bl = acpi_driver_data(device);
+       struct input_dev *input = fujitsu_bl->input;
 
        input_unregister_device(input);
 
-       fujitsu->acpi_handle = NULL;
+       fujitsu_bl->acpi_handle = NULL;
 
        return 0;
 }
 
 /* Brightness notify */
 
-static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
+static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
 {
        struct input_dev *input;
        int keycode;
        int oldb, newb;
 
-       input = fujitsu->input;
+       input = fujitsu_bl->input;
 
        switch (event) {
        case ACPI_FUJITSU_NOTIFY_CODE1:
                keycode = 0;
-               oldb = fujitsu->brightness_level;
+               oldb = fujitsu_bl->brightness_level;
                get_lcd_level();
-               newb = fujitsu->brightness_level;
+               newb = fujitsu_bl->brightness_level;
 
                vdbg_printk(FUJLAPTOP_DBG_TRACE,
                            "brightness button event [%i -> %i (%i)]\n",
-                           oldb, newb, fujitsu->brightness_changed);
+                           oldb, newb, fujitsu_bl->brightness_changed);
 
                if (oldb < newb) {
                        if (disable_brightness_adjust != 1) {
@@ -840,7 +841,7 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
 
 /* ACPI device for hotkey handling */
 
-static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
+static int acpi_fujitsu_laptop_add(struct acpi_device *device)
 {
        int result = 0;
        int state = 0;
@@ -851,42 +852,42 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
        if (!device)
                return -EINVAL;
 
-       fujitsu_hotkey->acpi_handle = device->handle;
+       fujitsu_laptop->acpi_handle = device->handle;
        sprintf(acpi_device_name(device), "%s",
-               ACPI_FUJITSU_HOTKEY_DEVICE_NAME);
+               ACPI_FUJITSU_LAPTOP_DEVICE_NAME);
        sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
-       device->driver_data = fujitsu_hotkey;
+       device->driver_data = fujitsu_laptop;
 
        /* kfifo */
-       spin_lock_init(&fujitsu_hotkey->fifo_lock);
-       error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int),
+       spin_lock_init(&fujitsu_laptop->fifo_lock);
+       error = kfifo_alloc(&fujitsu_laptop->fifo, RINGBUFFERSIZE * sizeof(int),
                        GFP_KERNEL);
        if (error) {
                pr_err("kfifo_alloc failed\n");
                goto err_stop;
        }
 
-       fujitsu_hotkey->input = input = input_allocate_device();
+       fujitsu_laptop->input = input = input_allocate_device();
        if (!input) {
                error = -ENOMEM;
                goto err_free_fifo;
        }
 
-       snprintf(fujitsu_hotkey->phys, sizeof(fujitsu_hotkey->phys),
+       snprintf(fujitsu_laptop->phys, sizeof(fujitsu_laptop->phys),
                 "%s/video/input0", acpi_device_hid(device));
 
        input->name = acpi_device_name(device);
-       input->phys = fujitsu_hotkey->phys;
+       input->phys = fujitsu_laptop->phys;
        input->id.bustype = BUS_HOST;
        input->id.product = 0x06;
        input->dev.parent = &device->dev;
 
        set_bit(EV_KEY, input->evbit);
-       set_bit(fujitsu->keycode1, input->keybit);
-       set_bit(fujitsu->keycode2, input->keybit);
-       set_bit(fujitsu->keycode3, input->keybit);
-       set_bit(fujitsu->keycode4, input->keybit);
-       set_bit(fujitsu->keycode5, input->keybit);
+       set_bit(fujitsu_bl->keycode1, input->keybit);
+       set_bit(fujitsu_bl->keycode2, input->keybit);
+       set_bit(fujitsu_bl->keycode3, input->keybit);
+       set_bit(fujitsu_bl->keycode4, input->keybit);
+       set_bit(fujitsu_bl->keycode5, input->keybit);
        set_bit(KEY_TOUCHPAD_TOGGLE, input->keybit);
        set_bit(KEY_UNKNOWN, input->keybit);
 
@@ -894,7 +895,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
        if (error)
                goto err_free_input_dev;
 
-       error = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state);
+       error = acpi_bus_update_power(fujitsu_laptop->acpi_handle, &state);
        if (error) {
                pr_err("Error reading power state\n");
                goto err_unregister_input_dev;
@@ -904,7 +905,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
                acpi_device_name(device), acpi_device_bid(device),
                !device->power.state ? "on" : "off");
 
-       fujitsu_hotkey->dev = device;
+       fujitsu_laptop->dev = device;
 
        if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
                vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
@@ -920,27 +921,27 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
                ; /* No action, result is discarded */
        vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
 
-       fujitsu_hotkey->rfkill_supported =
-               call_fext_func(FUNC_RFKILL, 0x0, 0x0, 0x0);
+       fujitsu_laptop->flags_supported =
+               call_fext_func(FUNC_FLAGS, 0x0, 0x0, 0x0);
 
        /* Make sure our bitmask of supported functions is cleared if the
           RFKILL function block is not implemented, like on the S7020. */
-       if (fujitsu_hotkey->rfkill_supported == UNSUPPORTED_CMD)
-               fujitsu_hotkey->rfkill_supported = 0;
+       if (fujitsu_laptop->flags_supported == UNSUPPORTED_CMD)
+               fujitsu_laptop->flags_supported = 0;
 
-       if (fujitsu_hotkey->rfkill_supported)
-               fujitsu_hotkey->rfkill_state =
-                       call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+       if (fujitsu_laptop->flags_supported)
+               fujitsu_laptop->flags_state =
+                       call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0);
 
        /* Suspect this is a keymap of the application panel, print it */
        pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
 
 #if IS_ENABLED(CONFIG_LEDS_CLASS)
        if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
-               result = led_classdev_register(&fujitsu->pf_device->dev,
+               result = led_classdev_register(&fujitsu_bl->pf_device->dev,
                                                &logolamp_led);
                if (result == 0) {
-                       fujitsu_hotkey->logolamp_registered = 1;
+                       fujitsu_laptop->logolamp_registered = 1;
                } else {
                        pr_err("Could not register LED handler for logo lamp, error %i\n",
                               result);
@@ -949,10 +950,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
 
        if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
           (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
-               result = led_classdev_register(&fujitsu->pf_device->dev,
+               result = led_classdev_register(&fujitsu_bl->pf_device->dev,
                                                &kblamps_led);
                if (result == 0) {
-                       fujitsu_hotkey->kblamps_registered = 1;
+                       fujitsu_laptop->kblamps_registered = 1;
                } else {
                        pr_err("Could not register LED handler for keyboard lamps, error %i\n",
                               result);
@@ -966,10 +967,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
         * that an RF LED is present.
         */
        if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) {
-               result = led_classdev_register(&fujitsu->pf_device->dev,
+               result = led_classdev_register(&fujitsu_bl->pf_device->dev,
                                                &radio_led);
                if (result == 0) {
-                       fujitsu_hotkey->radio_led_registered = 1;
+                       fujitsu_laptop->radio_led_registered = 1;
                } else {
                        pr_err("Could not register LED handler for radio LED, error %i\n",
                               result);
@@ -983,10 +984,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
        */
        if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
           (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
-               result = led_classdev_register(&fujitsu->pf_device->dev,
+               result = led_classdev_register(&fujitsu_bl->pf_device->dev,
                                                &eco_led);
                if (result == 0) {
-                       fujitsu_hotkey->eco_led_registered = 1;
+                       fujitsu_laptop->eco_led_registered = 1;
                } else {
                        pr_err("Could not register LED handler for eco LED, error %i\n",
                               result);
@@ -1002,47 +1003,47 @@ err_unregister_input_dev:
 err_free_input_dev:
        input_free_device(input);
 err_free_fifo:
-       kfifo_free(&fujitsu_hotkey->fifo);
+       kfifo_free(&fujitsu_laptop->fifo);
 err_stop:
        return error;
 }
 
-static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)
+static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
 {
-       struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device);
-       struct input_dev *input = fujitsu_hotkey->input;
+       struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device);
+       struct input_dev *input = fujitsu_laptop->input;
 
 #if IS_ENABLED(CONFIG_LEDS_CLASS)
-       if (fujitsu_hotkey->logolamp_registered)
+       if (fujitsu_laptop->logolamp_registered)
                led_classdev_unregister(&logolamp_led);
 
-       if (fujitsu_hotkey->kblamps_registered)
+       if (fujitsu_laptop->kblamps_registered)
                led_classdev_unregister(&kblamps_led);
 
-       if (fujitsu_hotkey->radio_led_registered)
+       if (fujitsu_laptop->radio_led_registered)
                led_classdev_unregister(&radio_led);
 
-       if (fujitsu_hotkey->eco_led_registered)
+       if (fujitsu_laptop->eco_led_registered)
                led_classdev_unregister(&eco_led);
 #endif
 
        input_unregister_device(input);
 
-       kfifo_free(&fujitsu_hotkey->fifo);
+       kfifo_free(&fujitsu_laptop->fifo);
 
-       fujitsu_hotkey->acpi_handle = NULL;
+       fujitsu_laptop->acpi_handle = NULL;
 
        return 0;
 }
 
-static void acpi_fujitsu_hotkey_press(int keycode)
+static void acpi_fujitsu_laptop_press(int keycode)
 {
-       struct input_dev *input = fujitsu_hotkey->input;
+       struct input_dev *input = fujitsu_laptop->input;
        int status;
 
-       status = kfifo_in_locked(&fujitsu_hotkey->fifo,
+       status = kfifo_in_locked(&fujitsu_laptop->fifo,
                                 (unsigned char *)&keycode, sizeof(keycode),
-                                &fujitsu_hotkey->fifo_lock);
+                                &fujitsu_laptop->fifo_lock);
        if (status != sizeof(keycode)) {
                vdbg_printk(FUJLAPTOP_DBG_WARN,
                            "Could not push keycode [0x%x]\n", keycode);
@@ -1054,16 +1055,16 @@ static void acpi_fujitsu_hotkey_press(int keycode)
                    "Push keycode into ringbuffer [%d]\n", keycode);
 }
 
-static void acpi_fujitsu_hotkey_release(void)
+static void acpi_fujitsu_laptop_release(void)
 {
-       struct input_dev *input = fujitsu_hotkey->input;
+       struct input_dev *input = fujitsu_laptop->input;
        int keycode, status;
 
        while (true) {
-               status = kfifo_out_locked(&fujitsu_hotkey->fifo,
+               status = kfifo_out_locked(&fujitsu_laptop->fifo,
                                          (unsigned char *)&keycode,
                                          sizeof(keycode),
-                                         &fujitsu_hotkey->fifo_lock);
+                                         &fujitsu_laptop->fifo_lock);
                if (status != sizeof(keycode))
                        return;
                input_report_key(input, keycode, 0);
@@ -1073,14 +1074,14 @@ static void acpi_fujitsu_hotkey_release(void)
        }
 }
 
-static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
+static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
 {
        struct input_dev *input;
        int keycode;
        unsigned int irb = 1;
        int i;
 
-       input = fujitsu_hotkey->input;
+       input = fujitsu_laptop->input;
 
        if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
                keycode = KEY_UNKNOWN;
@@ -1093,9 +1094,9 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
                return;
        }
 
-       if (fujitsu_hotkey->rfkill_supported)
-               fujitsu_hotkey->rfkill_state =
-                       call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+       if (fujitsu_laptop->flags_supported)
+               fujitsu_laptop->flags_state =
+                       call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0);
 
        i = 0;
        while ((irb =
@@ -1103,19 +1104,19 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
                        && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
                switch (irb & 0x4ff) {
                case KEY1_CODE:
-                       keycode = fujitsu->keycode1;
+                       keycode = fujitsu_bl->keycode1;
                        break;
                case KEY2_CODE:
-                       keycode = fujitsu->keycode2;
+                       keycode = fujitsu_bl->keycode2;
                        break;
                case KEY3_CODE:
-                       keycode = fujitsu->keycode3;
+                       keycode = fujitsu_bl->keycode3;
                        break;
                case KEY4_CODE:
-                       keycode = fujitsu->keycode4;
+                       keycode = fujitsu_bl->keycode4;
                        break;
                case KEY5_CODE:
-                       keycode = fujitsu->keycode5;
+                       keycode = fujitsu_bl->keycode5;
                        break;
                case 0:
                        keycode = 0;
@@ -1128,17 +1129,17 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
                }
 
                if (keycode > 0)
-                       acpi_fujitsu_hotkey_press(keycode);
+                       acpi_fujitsu_laptop_press(keycode);
                else if (keycode == 0)
-                       acpi_fujitsu_hotkey_release();
+                       acpi_fujitsu_laptop_release();
        }
 
        /* On some models (first seen on the Skylake-based Lifebook
         * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is
-        * handled in software; its state is queried using FUNC_RFKILL
+        * handled in software; its state is queried using FUNC_FLAGS
         */
-       if ((fujitsu_hotkey->rfkill_supported & BIT(26)) &&
-           (call_fext_func(FUNC_RFKILL, 0x1, 0x0, 0x0) & BIT(26))) {
+       if ((fujitsu_laptop->flags_supported & BIT(26)) &&
+           (call_fext_func(FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26))) {
                keycode = KEY_TOUCHPAD_TOGGLE;
                input_report_key(input, keycode, 1);
                input_sync(input);
@@ -1150,83 +1151,81 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
 
 /* Initialization */
 
-static const struct acpi_device_id fujitsu_device_ids[] = {
-       {ACPI_FUJITSU_HID, 0},
+static const struct acpi_device_id fujitsu_bl_device_ids[] = {
+       {ACPI_FUJITSU_BL_HID, 0},
        {"", 0},
 };
 
-static struct acpi_driver acpi_fujitsu_driver = {
-       .name = ACPI_FUJITSU_DRIVER_NAME,
+static struct acpi_driver acpi_fujitsu_bl_driver = {
+       .name = ACPI_FUJITSU_BL_DRIVER_NAME,
        .class = ACPI_FUJITSU_CLASS,
-       .ids = fujitsu_device_ids,
+       .ids = fujitsu_bl_device_ids,
        .ops = {
-               .add = acpi_fujitsu_add,
-               .remove = acpi_fujitsu_remove,
-               .notify = acpi_fujitsu_notify,
+               .add = acpi_fujitsu_bl_add,
+               .remove = acpi_fujitsu_bl_remove,
+               .notify = acpi_fujitsu_bl_notify,
                },
 };
 
-static const struct acpi_device_id fujitsu_hotkey_device_ids[] = {
-       {ACPI_FUJITSU_HOTKEY_HID, 0},
+static const struct acpi_device_id fujitsu_laptop_device_ids[] = {
+       {ACPI_FUJITSU_LAPTOP_HID, 0},
        {"", 0},
 };
 
-static struct acpi_driver acpi_fujitsu_hotkey_driver = {
-       .name = ACPI_FUJITSU_HOTKEY_DRIVER_NAME,
+static struct acpi_driver acpi_fujitsu_laptop_driver = {
+       .name = ACPI_FUJITSU_LAPTOP_DRIVER_NAME,
        .class = ACPI_FUJITSU_CLASS,
-       .ids = fujitsu_hotkey_device_ids,
+       .ids = fujitsu_laptop_device_ids,
        .ops = {
-               .add = acpi_fujitsu_hotkey_add,
-               .remove = acpi_fujitsu_hotkey_remove,
-               .notify = acpi_fujitsu_hotkey_notify,
+               .add = acpi_fujitsu_laptop_add,
+               .remove = acpi_fujitsu_laptop_remove,
+               .notify = acpi_fujitsu_laptop_notify,
                },
 };
 
 static const struct acpi_device_id fujitsu_ids[] __used = {
-       {ACPI_FUJITSU_HID, 0},
-       {ACPI_FUJITSU_HOTKEY_HID, 0},
+       {ACPI_FUJITSU_BL_HID, 0},
+       {ACPI_FUJITSU_LAPTOP_HID, 0},
        {"", 0}
 };
 MODULE_DEVICE_TABLE(acpi, fujitsu_ids);
 
 static int __init fujitsu_init(void)
 {
-       int ret, result, max_brightness;
+       int ret, max_brightness;
 
        if (acpi_disabled)
                return -ENODEV;
 
-       fujitsu = kzalloc(sizeof(struct fujitsu_t), GFP_KERNEL);
-       if (!fujitsu)
+       fujitsu_bl = kzalloc(sizeof(struct fujitsu_bl), GFP_KERNEL);
+       if (!fujitsu_bl)
                return -ENOMEM;
-       fujitsu->keycode1 = KEY_PROG1;
-       fujitsu->keycode2 = KEY_PROG2;
-       fujitsu->keycode3 = KEY_PROG3;
-       fujitsu->keycode4 = KEY_PROG4;
-       fujitsu->keycode5 = KEY_RFKILL;
+       fujitsu_bl->keycode1 = KEY_PROG1;
+       fujitsu_bl->keycode2 = KEY_PROG2;
+       fujitsu_bl->keycode3 = KEY_PROG3;
+       fujitsu_bl->keycode4 = KEY_PROG4;
+       fujitsu_bl->keycode5 = KEY_RFKILL;
        dmi_check_system(fujitsu_dmi_table);
 
-       result = acpi_bus_register_driver(&acpi_fujitsu_driver);
-       if (result < 0) {
-               ret = -ENODEV;
+       ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver);
+       if (ret)
                goto fail_acpi;
-       }
 
        /* Register platform stuff */
 
-       fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
-       if (!fujitsu->pf_device) {
+       fujitsu_bl->pf_device = platform_device_alloc("fujitsu-laptop", -1);
+       if (!fujitsu_bl->pf_device) {
                ret = -ENOMEM;
                goto fail_platform_driver;
        }
 
-       ret = platform_device_add(fujitsu->pf_device);
+       ret = platform_device_add(fujitsu_bl->pf_device);
        if (ret)
                goto fail_platform_device1;
 
        ret =
-           sysfs_create_group(&fujitsu->pf_device->dev.kobj,
-                              &fujitsupf_attribute_group);
+           sysfs_create_group(&fujitsu_bl->pf_device->dev.kobj,
+                              &fujitsu_pf_attribute_group);
        if (ret)
                goto fail_platform_device2;
 
@@ -1236,90 +1235,88 @@ static int __init fujitsu_init(void)
                struct backlight_properties props;
 
                memset(&props, 0, sizeof(struct backlight_properties));
-               max_brightness = fujitsu->max_brightness;
+               max_brightness = fujitsu_bl->max_brightness;
                props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = max_brightness - 1;
-               fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
-                                                              NULL, NULL,
-                                                              &fujitsubl_ops,
-                                                              &props);
-               if (IS_ERR(fujitsu->bl_device)) {
-                       ret = PTR_ERR(fujitsu->bl_device);
-                       fujitsu->bl_device = NULL;
+               fujitsu_bl->bl_device = backlight_device_register("fujitsu-laptop",
+                                                                 NULL, NULL,
+                                                                 &fujitsu_bl_ops,
+                                                                 &props);
+               if (IS_ERR(fujitsu_bl->bl_device)) {
+                       ret = PTR_ERR(fujitsu_bl->bl_device);
+                       fujitsu_bl->bl_device = NULL;
                        goto fail_sysfs_group;
                }
-               fujitsu->bl_device->props.brightness = fujitsu->brightness_level;
+               fujitsu_bl->bl_device->props.brightness = fujitsu_bl->brightness_level;
        }
 
-       ret = platform_driver_register(&fujitsupf_driver);
+       ret = platform_driver_register(&fujitsu_pf_driver);
        if (ret)
                goto fail_backlight;
 
-       /* Register hotkey driver */
+       /* Register laptop driver */
 
-       fujitsu_hotkey = kzalloc(sizeof(struct fujitsu_hotkey_t), GFP_KERNEL);
-       if (!fujitsu_hotkey) {
+       fujitsu_laptop = kzalloc(sizeof(struct fujitsu_laptop), GFP_KERNEL);
+       if (!fujitsu_laptop) {
                ret = -ENOMEM;
-               goto fail_hotkey;
+               goto fail_laptop;
        }
 
-       result = acpi_bus_register_driver(&acpi_fujitsu_hotkey_driver);
-       if (result < 0) {
-               ret = -ENODEV;
-               goto fail_hotkey1;
-       }
+       ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver);
+       if (ret)
+               goto fail_laptop1;
 
        /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */
        if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
                if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
-                       fujitsu->bl_device->props.power = FB_BLANK_POWERDOWN;
+                       fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN;
                else
-                       fujitsu->bl_device->props.power = FB_BLANK_UNBLANK;
+                       fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK;
        }
 
        pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n");
 
        return 0;
 
-fail_hotkey1:
-       kfree(fujitsu_hotkey);
-fail_hotkey:
-       platform_driver_unregister(&fujitsupf_driver);
+fail_laptop1:
+       kfree(fujitsu_laptop);
+fail_laptop:
+       platform_driver_unregister(&fujitsu_pf_driver);
 fail_backlight:
-       backlight_device_unregister(fujitsu->bl_device);
+       backlight_device_unregister(fujitsu_bl->bl_device);
 fail_sysfs_group:
-       sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
-                          &fujitsupf_attribute_group);
+       sysfs_remove_group(&fujitsu_bl->pf_device->dev.kobj,
+                          &fujitsu_pf_attribute_group);
 fail_platform_device2:
-       platform_device_del(fujitsu->pf_device);
+       platform_device_del(fujitsu_bl->pf_device);
 fail_platform_device1:
-       platform_device_put(fujitsu->pf_device);
+       platform_device_put(fujitsu_bl->pf_device);
 fail_platform_driver:
-       acpi_bus_unregister_driver(&acpi_fujitsu_driver);
+       acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
 fail_acpi:
-       kfree(fujitsu);
+       kfree(fujitsu_bl);
 
        return ret;
 }
 
 static void __exit fujitsu_cleanup(void)
 {
-       acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver);
+       acpi_bus_unregister_driver(&acpi_fujitsu_laptop_driver);
 
-       kfree(fujitsu_hotkey);
+       kfree(fujitsu_laptop);
 
-       platform_driver_unregister(&fujitsupf_driver);
+       platform_driver_unregister(&fujitsu_pf_driver);
 
-       backlight_device_unregister(fujitsu->bl_device);
+       backlight_device_unregister(fujitsu_bl->bl_device);
 
-       sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
-                          &fujitsupf_attribute_group);
+       sysfs_remove_group(&fujitsu_bl->pf_device->dev.kobj,
+                          &fujitsu_pf_attribute_group);
 
-       platform_device_unregister(fujitsu->pf_device);
+       platform_device_unregister(fujitsu_bl->pf_device);
 
-       acpi_bus_unregister_driver(&acpi_fujitsu_driver);
+       acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
 
-       kfree(fujitsu);
+       kfree(fujitsu_bl);
 
        pr_info("driver unloaded\n");
 }
@@ -1341,7 +1338,3 @@ MODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon");
 MODULE_DESCRIPTION("Fujitsu laptop extras support");
 MODULE_VERSION(FUJITSU_DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
-MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*");
-MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
index 65f86bc24c07c7032726700e09a1d9ef3cdfb3c2..1dc43fc5f65f38d8028388548452bd12218641fc 100644 (file)
@@ -76,7 +76,7 @@ config QCOM_ADSP_PIL
        depends on OF && ARCH_QCOM
        depends on REMOTEPROC
        depends on QCOM_SMEM
-       depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
+       depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && RPMSG_QCOM_SMD=n)
        select MFD_SYSCON
        select QCOM_MDT_LOADER
        select QCOM_RPROC_COMMON
@@ -93,7 +93,7 @@ config QCOM_Q6V5_PIL
        depends on OF && ARCH_QCOM
        depends on QCOM_SMEM
        depends on REMOTEPROC
-       depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
+       depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && RPMSG_QCOM_SMD=n)
        select MFD_SYSCON
        select QCOM_RPROC_COMMON
        select QCOM_SCM
@@ -104,7 +104,7 @@ config QCOM_Q6V5_PIL
 config QCOM_WCNSS_PIL
        tristate "Qualcomm WCNSS Peripheral Image Loader"
        depends on OF && ARCH_QCOM
-       depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
+       depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && RPMSG_QCOM_SMD=n)
        depends on QCOM_SMEM
        depends on REMOTEPROC
        select QCOM_MDT_LOADER
index 230043c1c90ffcfe5781bcdea23cc52dc9bc6732..3c52867dfe28e33b04f85858dfdb9285eef11ba2 100644 (file)
@@ -1241,16 +1241,15 @@ config SCSI_LPFC
        tristate "Emulex LightPulse Fibre Channel Support"
        depends on PCI && SCSI
        depends on SCSI_FC_ATTRS
-       depends on NVME_FC && NVME_TARGET_FC
        select CRC_T10DIF
-       help
+       ---help---
           This lpfc driver supports the Emulex LightPulse
           Family of Fibre Channel PCI host adapters.
 
 config SCSI_LPFC_DEBUG_FS
        bool "Emulex LightPulse Fibre Channel debugfs Support"
        depends on SCSI_LPFC && DEBUG_FS
-       help
+       ---help---
          This makes debugging information from the lpfc driver
          available via the debugfs filesystem.
 
index 2e5338dec621fbff89c8a68acc3ba241173f3239..7b0410e0f569481cc40101fab38a768c7e274c8e 100644 (file)
@@ -468,7 +468,7 @@ err_out:
        return -1;
 
 err_blink:
-       return (status > 16) & 0xFF;
+       return (status >> 16) & 0xFF;
 }
 
 static inline u32 aac_get_vector(struct aac_dev *dev)
index 524a0c755ed7e74cd790778ec7c04ae452cc853d..0d0be7754a653120a4e08c3897e37c572d3cda49 100644 (file)
@@ -2956,7 +2956,7 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
        /* fill_cmd can't fail here, no data buffer to map. */
        (void) fill_cmd(c, reset_type, h, NULL, 0, 0,
                        scsi3addr, TYPE_MSG);
-       rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT);
+       rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT);
        if (rc) {
                dev_warn(&h->pdev->dev, "Failed to send reset command\n");
                goto out;
@@ -3714,7 +3714,7 @@ exit_failed:
  *  # (integer code indicating one of several NOT READY states
  *     describing why a volume is to be kept offline)
  */
-static int hpsa_volume_offline(struct ctlr_info *h,
+static unsigned char hpsa_volume_offline(struct ctlr_info *h,
                                        unsigned char scsi3addr[])
 {
        struct CommandList *c;
@@ -3735,7 +3735,7 @@ static int hpsa_volume_offline(struct ctlr_info *h,
                                        DEFAULT_TIMEOUT);
        if (rc) {
                cmd_free(h, c);
-               return 0;
+               return HPSA_VPD_LV_STATUS_UNSUPPORTED;
        }
        sense = c->err_info->SenseInfo;
        if (c->err_info->SenseLen > sizeof(c->err_info->SenseInfo))
@@ -3746,19 +3746,13 @@ static int hpsa_volume_offline(struct ctlr_info *h,
        cmd_status = c->err_info->CommandStatus;
        scsi_status = c->err_info->ScsiStatus;
        cmd_free(h, c);
-       /* Is the volume 'not ready'? */
-       if (cmd_status != CMD_TARGET_STATUS ||
-               scsi_status != SAM_STAT_CHECK_CONDITION ||
-               sense_key != NOT_READY ||
-               asc != ASC_LUN_NOT_READY)  {
-               return 0;
-       }
 
        /* Determine the reason for not ready state */
        ldstat = hpsa_get_volume_status(h, scsi3addr);
 
        /* Keep volume offline in certain cases: */
        switch (ldstat) {
+       case HPSA_LV_FAILED:
        case HPSA_LV_UNDERGOING_ERASE:
        case HPSA_LV_NOT_AVAILABLE:
        case HPSA_LV_UNDERGOING_RPI:
@@ -3780,7 +3774,7 @@ static int hpsa_volume_offline(struct ctlr_info *h,
        default:
                break;
        }
-       return 0;
+       return HPSA_LV_OK;
 }
 
 /*
@@ -3853,10 +3847,10 @@ static int hpsa_update_device_info(struct ctlr_info *h,
        /* Do an inquiry to the device to see what it is. */
        if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
                (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
-               /* Inquiry failed (msg printed already) */
                dev_err(&h->pdev->dev,
-                       "hpsa_update_device_info: inquiry failed\n");
-               rc = -EIO;
+                       "%s: inquiry failed, device will be skipped.\n",
+                       __func__);
+               rc = HPSA_INQUIRY_FAILED;
                goto bail_out;
        }
 
@@ -3885,15 +3879,19 @@ static int hpsa_update_device_info(struct ctlr_info *h,
        if ((this_device->devtype == TYPE_DISK ||
                this_device->devtype == TYPE_ZBC) &&
                is_logical_dev_addr_mode(scsi3addr)) {
-               int volume_offline;
+               unsigned char volume_offline;
 
                hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level);
                if (h->fw_support & MISC_FW_RAID_OFFLOAD_BASIC)
                        hpsa_get_ioaccel_status(h, scsi3addr, this_device);
                volume_offline = hpsa_volume_offline(h, scsi3addr);
-               if (volume_offline < 0 || volume_offline > 0xff)
-                       volume_offline = HPSA_VPD_LV_STATUS_UNSUPPORTED;
-               this_device->volume_offline = volume_offline & 0xff;
+               if (volume_offline == HPSA_LV_FAILED) {
+                       rc = HPSA_LV_FAILED;
+                       dev_err(&h->pdev->dev,
+                               "%s: LV failed, device will be skipped.\n",
+                               __func__);
+                       goto bail_out;
+               }
        } else {
                this_device->raid_level = RAID_UNKNOWN;
                this_device->offload_config = 0;
@@ -4379,8 +4377,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
                        goto out;
                }
                if (rc) {
-                       dev_warn(&h->pdev->dev,
-                               "Inquiry failed, skipping device.\n");
+                       h->drv_req_rescan = 1;
                        continue;
                }
 
@@ -5558,7 +5555,7 @@ static void hpsa_scan_complete(struct ctlr_info *h)
 
        spin_lock_irqsave(&h->scan_lock, flags);
        h->scan_finished = 1;
-       wake_up_all(&h->scan_wait_queue);
+       wake_up(&h->scan_wait_queue);
        spin_unlock_irqrestore(&h->scan_lock, flags);
 }
 
@@ -5576,11 +5573,23 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
        if (unlikely(lockup_detected(h)))
                return hpsa_scan_complete(h);
 
+       /*
+        * If a scan is already waiting to run, no need to add another
+        */
+       spin_lock_irqsave(&h->scan_lock, flags);
+       if (h->scan_waiting) {
+               spin_unlock_irqrestore(&h->scan_lock, flags);
+               return;
+       }
+
+       spin_unlock_irqrestore(&h->scan_lock, flags);
+
        /* wait until any scan already in progress is finished. */
        while (1) {
                spin_lock_irqsave(&h->scan_lock, flags);
                if (h->scan_finished)
                        break;
+               h->scan_waiting = 1;
                spin_unlock_irqrestore(&h->scan_lock, flags);
                wait_event(h->scan_wait_queue, h->scan_finished);
                /* Note: We don't need to worry about a race between this
@@ -5590,6 +5599,7 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
                 */
        }
        h->scan_finished = 0; /* mark scan as in progress */
+       h->scan_waiting = 0;
        spin_unlock_irqrestore(&h->scan_lock, flags);
 
        if (unlikely(lockup_detected(h)))
@@ -8792,6 +8802,7 @@ reinit_after_soft_reset:
        init_waitqueue_head(&h->event_sync_wait_queue);
        mutex_init(&h->reset_mutex);
        h->scan_finished = 1; /* no scan currently in progress */
+       h->scan_waiting = 0;
 
        pci_set_drvdata(pdev, h);
        h->ndevices = 0;
index bf6cdc1066544fa5fe2df6f5396d17ca4b4c8909..6f04f2ad412530a76d615b394250d502221d5457 100644 (file)
@@ -201,6 +201,7 @@ struct ctlr_info {
        dma_addr_t              errinfo_pool_dhandle;
        unsigned long           *cmd_pool_bits;
        int                     scan_finished;
+       u8                      scan_waiting : 1;
        spinlock_t              scan_lock;
        wait_queue_head_t       scan_wait_queue;
 
index a584cdf0705846ef13a0375ecb2e1579513ecf92..5961705eef767526f66a6dbc1bbb1e7feec70c85 100644 (file)
 #define CFGTBL_BusType_Fibre2G  0x00000200l
 
 /* VPD Inquiry types */
+#define HPSA_INQUIRY_FAILED            0x02
 #define HPSA_VPD_SUPPORTED_PAGES        0x00
 #define HPSA_VPD_LV_DEVICE_ID           0x83
 #define HPSA_VPD_LV_DEVICE_GEOMETRY     0xC1
 /* Logical volume states */
 #define HPSA_VPD_LV_STATUS_UNSUPPORTED                 0xff
 #define HPSA_LV_OK                                      0x0
+#define HPSA_LV_FAILED                                 0x01
 #define HPSA_LV_NOT_AVAILABLE                          0x0b
 #define HPSA_LV_UNDERGOING_ERASE                       0x0F
 #define HPSA_LV_UNDERGOING_RPI                         0x12
index 07c08ce68d70af2fc09be51a3f4c8ba67c5a1d9d..894b1e3ebd56f4a141a8ed49a298819e3abbe8b2 100644 (file)
@@ -561,8 +561,12 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
        WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
        task->state = state;
 
-       if (!list_empty(&task->running))
+       spin_lock_bh(&conn->taskqueuelock);
+       if (!list_empty(&task->running)) {
+               pr_debug_once("%s while task on list", __func__);
                list_del_init(&task->running);
+       }
+       spin_unlock_bh(&conn->taskqueuelock);
 
        if (conn->task == task)
                conn->task = NULL;
@@ -784,7 +788,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
                if (session->tt->xmit_task(task))
                        goto free_task;
        } else {
+               spin_lock_bh(&conn->taskqueuelock);
                list_add_tail(&task->running, &conn->mgmtqueue);
+               spin_unlock_bh(&conn->taskqueuelock);
                iscsi_conn_queue_work(conn);
        }
 
@@ -1475,8 +1481,10 @@ void iscsi_requeue_task(struct iscsi_task *task)
         * this may be on the requeue list already if the xmit_task callout
         * is handling the r2ts while we are adding new ones
         */
+       spin_lock_bh(&conn->taskqueuelock);
        if (list_empty(&task->running))
                list_add_tail(&task->running, &conn->requeue);
+       spin_unlock_bh(&conn->taskqueuelock);
        iscsi_conn_queue_work(conn);
 }
 EXPORT_SYMBOL_GPL(iscsi_requeue_task);
@@ -1513,22 +1521,26 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
         * only have one nop-out as a ping from us and targets should not
         * overflow us with nop-ins
         */
+       spin_lock_bh(&conn->taskqueuelock);
 check_mgmt:
        while (!list_empty(&conn->mgmtqueue)) {
                conn->task = list_entry(conn->mgmtqueue.next,
                                         struct iscsi_task, running);
                list_del_init(&conn->task->running);
+               spin_unlock_bh(&conn->taskqueuelock);
                if (iscsi_prep_mgmt_task(conn, conn->task)) {
                        /* regular RX path uses back_lock */
                        spin_lock_bh(&conn->session->back_lock);
                        __iscsi_put_task(conn->task);
                        spin_unlock_bh(&conn->session->back_lock);
                        conn->task = NULL;
+                       spin_lock_bh(&conn->taskqueuelock);
                        continue;
                }
                rc = iscsi_xmit_task(conn);
                if (rc)
                        goto done;
+               spin_lock_bh(&conn->taskqueuelock);
        }
 
        /* process pending command queue */
@@ -1536,19 +1548,24 @@ check_mgmt:
                conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task,
                                        running);
                list_del_init(&conn->task->running);
+               spin_unlock_bh(&conn->taskqueuelock);
                if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
                        fail_scsi_task(conn->task, DID_IMM_RETRY);
+                       spin_lock_bh(&conn->taskqueuelock);
                        continue;
                }
                rc = iscsi_prep_scsi_cmd_pdu(conn->task);
                if (rc) {
                        if (rc == -ENOMEM || rc == -EACCES) {
+                               spin_lock_bh(&conn->taskqueuelock);
                                list_add_tail(&conn->task->running,
                                              &conn->cmdqueue);
                                conn->task = NULL;
+                               spin_unlock_bh(&conn->taskqueuelock);
                                goto done;
                        } else
                                fail_scsi_task(conn->task, DID_ABORT);
+                       spin_lock_bh(&conn->taskqueuelock);
                        continue;
                }
                rc = iscsi_xmit_task(conn);
@@ -1559,6 +1576,7 @@ check_mgmt:
                 * we need to check the mgmt queue for nops that need to
                 * be sent to aviod starvation
                 */
+               spin_lock_bh(&conn->taskqueuelock);
                if (!list_empty(&conn->mgmtqueue))
                        goto check_mgmt;
        }
@@ -1578,12 +1596,15 @@ check_mgmt:
                conn->task = task;
                list_del_init(&conn->task->running);
                conn->task->state = ISCSI_TASK_RUNNING;
+               spin_unlock_bh(&conn->taskqueuelock);
                rc = iscsi_xmit_task(conn);
                if (rc)
                        goto done;
+               spin_lock_bh(&conn->taskqueuelock);
                if (!list_empty(&conn->mgmtqueue))
                        goto check_mgmt;
        }
+       spin_unlock_bh(&conn->taskqueuelock);
        spin_unlock_bh(&conn->session->frwd_lock);
        return -ENODATA;
 
@@ -1739,7 +1760,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
                        goto prepd_reject;
                }
        } else {
+               spin_lock_bh(&conn->taskqueuelock);
                list_add_tail(&task->running, &conn->cmdqueue);
+               spin_unlock_bh(&conn->taskqueuelock);
                iscsi_conn_queue_work(conn);
        }
 
@@ -2897,6 +2920,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
        INIT_LIST_HEAD(&conn->mgmtqueue);
        INIT_LIST_HEAD(&conn->cmdqueue);
        INIT_LIST_HEAD(&conn->requeue);
+       spin_lock_init(&conn->taskqueuelock);
        INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
 
        /* allocate login_task used for the login/text sequences */
index 0bba2e30b4f09f62ef096ce73df629681a1646b6..257bbdd0f0b83a54d36d0378db18dedb93472737 100644 (file)
@@ -99,12 +99,13 @@ struct lpfc_sli2_slim;
 #define FC_MAX_ADPTMSG         64
 
 #define MAX_HBAEVT     32
+#define MAX_HBAS_NO_RESET 16
 
 /* Number of MSI-X vectors the driver uses */
 #define LPFC_MSIX_VECTORS      2
 
 /* lpfc wait event data ready flag */
-#define LPFC_DATA_READY                (1<<0)
+#define LPFC_DATA_READY                0       /* bit 0 */
 
 /* queue dump line buffer size */
 #define LPFC_LBUF_SZ           128
@@ -692,6 +693,7 @@ struct lpfc_hba {
                                         * capability
                                         */
 #define HBA_NVME_IOQ_FLUSH      0x80000 /* NVME IO queues flushed. */
+#define NVME_XRI_ABORT_EVENT   0x100000
 
        uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
        struct lpfc_dmabuf slim2p;
index 5c783ef7f260612e881dd199bccd767d9179a99d..22819afbaef5c4a229ce66ebdf8d681b47fbbc2f 100644 (file)
@@ -3010,6 +3010,12 @@ MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
 static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
                   lpfc_poll_show, lpfc_poll_store);
 
+int lpfc_no_hba_reset_cnt;
+unsigned long lpfc_no_hba_reset[MAX_HBAS_NO_RESET] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+module_param_array(lpfc_no_hba_reset, ulong, &lpfc_no_hba_reset_cnt, 0444);
+MODULE_PARM_DESC(lpfc_no_hba_reset, "WWPN of HBAs that should not be reset");
+
 LPFC_ATTR(sli_mode, 0, 0, 3,
        "SLI mode selector:"
        " 0 - auto (SLI-3 if supported),"
@@ -3309,9 +3315,9 @@ LPFC_ATTR_R(nvmet_mrq_post, LPFC_DEF_MRQ_POST,
  * lpfc_enable_fc4_type: Defines what FC4 types are supported.
  * Supported Values:  1 - register just FCP
  *                    3 - register both FCP and NVME
- * Supported values are [1,3]. Default value is 3
+ * Supported values are [1,3]. Default value is 1
  */
-LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_BOTH,
+LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_FCP,
            LPFC_ENABLE_FCP, LPFC_ENABLE_BOTH,
            "Define fc4 type to register with fabric.");
 
@@ -4451,7 +4457,8 @@ lpfc_fcp_imax_store(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        phba->cfg_fcp_imax = (uint32_t)val;
-       for (i = 0; i < phba->io_channel_irqs; i++)
+
+       for (i = 0; i < phba->io_channel_irqs; i += LPFC_MAX_EQ_DELAY_EQID_CNT)
                lpfc_modify_hba_eq_delay(phba, i);
 
        return strlen(buf);
index 843dd73004da0239089442a8591bd2c37e141f16..54e6ac42fbcd4269e2272c5b81271d607232da0a 100644 (file)
@@ -384,7 +384,7 @@ void lpfc_free_sysfs_attr(struct lpfc_vport *);
 extern struct device_attribute *lpfc_hba_attrs[];
 extern struct device_attribute *lpfc_vport_attrs[];
 extern struct scsi_host_template lpfc_template;
-extern struct scsi_host_template lpfc_template_s3;
+extern struct scsi_host_template lpfc_template_no_hr;
 extern struct scsi_host_template lpfc_template_nvme;
 extern struct scsi_host_template lpfc_vport_template;
 extern struct fc_function_template lpfc_transport_functions;
@@ -554,3 +554,5 @@ void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba,
                                struct lpfc_wcqe_complete *abts_cmpl);
 extern int lpfc_enable_nvmet_cnt;
 extern unsigned long long lpfc_enable_nvmet[];
+extern int lpfc_no_hba_reset_cnt;
+extern unsigned long lpfc_no_hba_reset[];
index c22bb3f887e15b767c8cc53334389cba053c50a9..d3e9af983015ccfc1408a99b61ee190e9730098c 100644 (file)
@@ -939,8 +939,8 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                         "FC4 x%08x, Data: x%08x x%08x\n",
                                         ndlp, did, ndlp->nlp_fc4_type,
                                         FC_TYPE_FCP, FC_TYPE_NVME);
+                       ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
                }
-               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
                lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
                lpfc_issue_els_prli(vport, ndlp, 0);
        } else
index 9f4798e9d9380dab26d1a506fcf5fe1c43dd7493..913eed822cb8ed85d4d726a2ee3150c7760a4f47 100644 (file)
@@ -3653,17 +3653,6 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        idiag.ptr_private = phba->sli4_hba.nvmels_cq;
                        goto pass_check;
                }
-               /* NVME LS complete queue */
-               if (phba->sli4_hba.nvmels_cq &&
-                   phba->sli4_hba.nvmels_cq->queue_id == queid) {
-                       /* Sanity check */
-                       rc = lpfc_idiag_que_param_check(
-                                       phba->sli4_hba.nvmels_cq, index, count);
-                       if (rc)
-                               goto error_out;
-                       idiag.ptr_private = phba->sli4_hba.nvmels_cq;
-                       goto pass_check;
-               }
                /* FCP complete queue */
                if (phba->sli4_hba.fcp_cq) {
                        for (qidx = 0; qidx < phba->cfg_fcp_io_channel;
@@ -3738,17 +3727,6 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        idiag.ptr_private = phba->sli4_hba.nvmels_wq;
                        goto pass_check;
                }
-               /* NVME LS work queue */
-               if (phba->sli4_hba.nvmels_wq &&
-                   phba->sli4_hba.nvmels_wq->queue_id == queid) {
-                       /* Sanity check */
-                       rc = lpfc_idiag_que_param_check(
-                                       phba->sli4_hba.nvmels_wq, index, count);
-                       if (rc)
-                               goto error_out;
-                       idiag.ptr_private = phba->sli4_hba.nvmels_wq;
-                       goto pass_check;
-               }
                /* FCP work queue */
                if (phba->sli4_hba.fcp_wq) {
                        for (qidx = 0; qidx < phba->cfg_fcp_io_channel;
index 2d26440e6f2fe6b3d9d2bc457c112397601409cf..d9c61d030034da95854d2524406c17c202a317b9 100644 (file)
@@ -5177,15 +5177,15 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
 
 static uint32_t
 lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc,
-               struct lpfc_hba *phba)
+               struct lpfc_vport *vport)
 {
 
        desc->tag = cpu_to_be32(RDP_PORT_NAMES_DESC_TAG);
 
-       memcpy(desc->port_names.wwnn, phba->wwnn,
+       memcpy(desc->port_names.wwnn, &vport->fc_nodename,
                        sizeof(desc->port_names.wwnn));
 
-       memcpy(desc->port_names.wwpn, phba->wwpn,
+       memcpy(desc->port_names.wwpn, &vport->fc_portname,
                        sizeof(desc->port_names.wwpn));
 
        desc->length = cpu_to_be32(sizeof(desc->port_names));
@@ -5279,7 +5279,7 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
        len += lpfc_rdp_res_link_error((struct fc_rdp_link_error_status_desc *)
                                       (len + pcmd), &rdp_context->link_stat);
        len += lpfc_rdp_res_diag_port_names((struct fc_rdp_port_name_desc *)
-                                            (len + pcmd), phba);
+                                            (len + pcmd), vport);
        len += lpfc_rdp_res_attach_port_names((struct fc_rdp_port_name_desc *)
                                        (len + pcmd), vport, ndlp);
        len += lpfc_rdp_res_fec_desc((struct fc_fec_rdp_desc *)(len + pcmd),
@@ -8371,11 +8371,17 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                        spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
                        spin_unlock_irq(shost->host_lock);
-                       if (vport->port_type == LPFC_PHYSICAL_PORT
-                               && !(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG))
-                               lpfc_issue_init_vfi(vport);
-                       else
+                       if (mb->mbxStatus == MBX_NOT_FINISHED)
+                               break;
+                       if ((vport->port_type == LPFC_PHYSICAL_PORT) &&
+                           !(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG)) {
+                               if (phba->sli_rev == LPFC_SLI_REV4)
+                                       lpfc_issue_init_vfi(vport);
+                               else
+                                       lpfc_initial_flogi(vport);
+                       } else {
                                lpfc_initial_fdisc(vport);
+                       }
                        break;
                }
        } else {
index 194a14d5f8a9821bf7c3ddc562049db294ce3e07..180b072beef6b079c756474d889e3a494ad75131 100644 (file)
@@ -313,8 +313,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
                                 ndlp->nlp_state, ndlp->nlp_rpi);
        }
 
-       if (!(vport->load_flag & FC_UNLOADING) &&
-           !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+       if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
            !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
            (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
            (ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) &&
@@ -641,6 +640,8 @@ lpfc_work_done(struct lpfc_hba *phba)
                        lpfc_handle_rrq_active(phba);
                if (phba->hba_flag & FCP_XRI_ABORT_EVENT)
                        lpfc_sli4_fcp_xri_abort_event_proc(phba);
+               if (phba->hba_flag & NVME_XRI_ABORT_EVENT)
+                       lpfc_sli4_nvme_xri_abort_event_proc(phba);
                if (phba->hba_flag & ELS_XRI_ABORT_EVENT)
                        lpfc_sli4_els_xri_abort_event_proc(phba);
                if (phba->hba_flag & ASYNC_EVENT)
@@ -2173,7 +2174,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        uint32_t boot_flag, addr_mode;
        uint16_t fcf_index, next_fcf_index;
        struct lpfc_fcf_rec *fcf_rec = NULL;
-       uint16_t vlan_id;
+       uint16_t vlan_id = LPFC_FCOE_NULL_VID;
        bool select_new_fcf;
        int rc;
 
@@ -4020,9 +4021,11 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                rdata = rport->dd_data;
                /* break the link before dropping the ref */
                ndlp->rport = NULL;
-               if (rdata && rdata->pnode == ndlp)
-                       lpfc_nlp_put(ndlp);
-               rdata->pnode = NULL;
+               if (rdata) {
+                       if (rdata->pnode == ndlp)
+                               lpfc_nlp_put(ndlp);
+                       rdata->pnode = NULL;
+               }
                /* drop reference for earlier registeration */
                put_device(&rport->dev);
        }
@@ -4344,9 +4347,8 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 {
        INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
        INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
-       init_timer(&ndlp->nlp_delayfunc);
-       ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
-       ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
+       setup_timer(&ndlp->nlp_delayfunc, lpfc_els_retry_delay,
+                       (unsigned long)ndlp);
        ndlp->nlp_DID = did;
        ndlp->vport = vport;
        ndlp->phba = vport->phba;
@@ -4606,9 +4608,9 @@ lpfc_sli4_dequeue_nport_iocbs(struct lpfc_hba *phba,
                pring = qp->pring;
                if (!pring)
                        continue;
-               spin_lock_irq(&pring->ring_lock);
+               spin_lock(&pring->ring_lock);
                __lpfc_dequeue_nport_iocbs(phba, ndlp, pring, dequeue_list);
-               spin_unlock_irq(&pring->ring_lock);
+               spin_unlock(&pring->ring_lock);
        }
        spin_unlock_irq(&phba->hbalock);
 }
index cfdb068a3bfccb76046fbc8d0cb000e80bc905ff..15277705cb6b8c650880572837954d91b6bc01eb 100644 (file)
@@ -1001,7 +1001,7 @@ struct eq_delay_info {
        uint32_t phase;
        uint32_t delay_multi;
 };
-#define        LPFC_MAX_EQ_DELAY       8
+#define        LPFC_MAX_EQ_DELAY_EQID_CNT      8
 
 struct sgl_page_pairs {
        uint32_t sgl_pg0_addr_lo;
@@ -1070,7 +1070,7 @@ struct lpfc_mbx_modify_eq_delay {
        union {
                struct {
                        uint32_t num_eq;
-                       struct eq_delay_info eq[LPFC_MAX_EQ_DELAY];
+                       struct eq_delay_info eq[LPFC_MAX_EQ_DELAY_EQID_CNT];
                } request;
                struct {
                        uint32_t word0;
index 0ee429d773f394e826074e6580bbd73c212e26ba..6cc561b042118ed6d172dddb8221d77c8a793ee4 100644 (file)
@@ -3555,6 +3555,44 @@ out_free_mem:
        return rc;
 }
 
+static uint64_t
+lpfc_get_wwpn(struct lpfc_hba *phba)
+{
+       uint64_t wwn;
+       int rc;
+       LPFC_MBOXQ_t *mboxq;
+       MAILBOX_t *mb;
+
+
+       mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+                                               GFP_KERNEL);
+       if (!mboxq)
+               return (uint64_t)-1;
+
+       /* First get WWN of HBA instance */
+       lpfc_read_nv(phba, mboxq);
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       if (rc != MBX_SUCCESS) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "6019 Mailbox failed , mbxCmd x%x "
+                               "READ_NV, mbxStatus x%x\n",
+                               bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+                               bf_get(lpfc_mqe_status, &mboxq->u.mqe));
+               mempool_free(mboxq, phba->mbox_mem_pool);
+               return (uint64_t) -1;
+       }
+       mb = &mboxq->u.mb;
+       memcpy(&wwn, (char *)mb->un.varRDnvp.portname, sizeof(uint64_t));
+       /* wwn is WWPN of HBA instance */
+       mempool_free(mboxq, phba->mbox_mem_pool);
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               return be64_to_cpu(wwn);
+       else
+               return (((wwn & 0xffffffff00000000) >> 32) |
+                       ((wwn & 0x00000000ffffffff) << 32));
+
+}
+
 /**
  * lpfc_sli4_nvme_sgl_update - update xri-sgl sizing and mapping
  * @phba: pointer to lpfc hba data structure.
@@ -3676,17 +3714,32 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        struct lpfc_vport *vport;
        struct Scsi_Host  *shost = NULL;
        int error = 0;
+       int i;
+       uint64_t wwn;
+       bool use_no_reset_hba = false;
+
+       wwn = lpfc_get_wwpn(phba);
+
+       for (i = 0; i < lpfc_no_hba_reset_cnt; i++) {
+               if (wwn == lpfc_no_hba_reset[i]) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "6020 Setting use_no_reset port=%llx\n",
+                                       wwn);
+                       use_no_reset_hba = true;
+                       break;
+               }
+       }
 
        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) {
                if (dev != &phba->pcidev->dev) {
                        shost = scsi_host_alloc(&lpfc_vport_template,
                                                sizeof(struct lpfc_vport));
                } else {
-                       if (phba->sli_rev == LPFC_SLI_REV4)
+                       if (!use_no_reset_hba)
                                shost = scsi_host_alloc(&lpfc_template,
                                                sizeof(struct lpfc_vport));
                        else
-                               shost = scsi_host_alloc(&lpfc_template_s3,
+                               shost = scsi_host_alloc(&lpfc_template_no_hr,
                                                sizeof(struct lpfc_vport));
                }
        } else if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
@@ -3734,17 +3787,14 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        INIT_LIST_HEAD(&vport->rcv_buffer_list);
        spin_lock_init(&vport->work_port_lock);
 
-       init_timer(&vport->fc_disctmo);
-       vport->fc_disctmo.function = lpfc_disc_timeout;
-       vport->fc_disctmo.data = (unsigned long)vport;
+       setup_timer(&vport->fc_disctmo, lpfc_disc_timeout,
+                       (unsigned long)vport);
 
-       init_timer(&vport->els_tmofunc);
-       vport->els_tmofunc.function = lpfc_els_timeout;
-       vport->els_tmofunc.data = (unsigned long)vport;
+       setup_timer(&vport->els_tmofunc, lpfc_els_timeout,
+                       (unsigned long)vport);
 
-       init_timer(&vport->delayed_disc_tmo);
-       vport->delayed_disc_tmo.function = lpfc_delayed_disc_tmo;
-       vport->delayed_disc_tmo.data = (unsigned long)vport;
+       setup_timer(&vport->delayed_disc_tmo, lpfc_delayed_disc_tmo,
+                       (unsigned long)vport);
 
        error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
        if (error)
@@ -5406,21 +5456,15 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
        INIT_LIST_HEAD(&phba->luns);
 
        /* MBOX heartbeat timer */
-       init_timer(&psli->mbox_tmo);
-       psli->mbox_tmo.function = lpfc_mbox_timeout;
-       psli->mbox_tmo.data = (unsigned long) phba;
+       setup_timer(&psli->mbox_tmo, lpfc_mbox_timeout, (unsigned long)phba);
        /* Fabric block timer */
-       init_timer(&phba->fabric_block_timer);
-       phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
-       phba->fabric_block_timer.data = (unsigned long) phba;
+       setup_timer(&phba->fabric_block_timer, lpfc_fabric_block_timeout,
+                       (unsigned long)phba);
        /* EA polling mode timer */
-       init_timer(&phba->eratt_poll);
-       phba->eratt_poll.function = lpfc_poll_eratt;
-       phba->eratt_poll.data = (unsigned long) phba;
+       setup_timer(&phba->eratt_poll, lpfc_poll_eratt,
+                       (unsigned long)phba);
        /* Heartbeat timer */
-       init_timer(&phba->hb_tmofunc);
-       phba->hb_tmofunc.function = lpfc_hb_timeout;
-       phba->hb_tmofunc.data = (unsigned long)phba;
+       setup_timer(&phba->hb_tmofunc, lpfc_hb_timeout, (unsigned long)phba);
 
        return 0;
 }
@@ -5446,9 +5490,8 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
         */
 
        /* FCP polling mode timer */
-       init_timer(&phba->fcp_poll_timer);
-       phba->fcp_poll_timer.function = lpfc_poll_timeout;
-       phba->fcp_poll_timer.data = (unsigned long) phba;
+       setup_timer(&phba->fcp_poll_timer, lpfc_poll_timeout,
+                       (unsigned long)phba);
 
        /* Host attention work mask setup */
        phba->work_ha_mask = (HA_ERATT | HA_MBATT | HA_LATT);
@@ -5482,7 +5525,8 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
 
        /* Initialize the host templates the configured values. */
        lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
-       lpfc_template_s3.sg_tablesize = phba->cfg_sg_seg_cnt;
+       lpfc_template_no_hr.sg_tablesize = phba->cfg_sg_seg_cnt;
+       lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
 
        /* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */
        if (phba->cfg_enable_bg) {
@@ -5617,14 +5661,11 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
         * Initialize timers used by driver
         */
 
-       init_timer(&phba->rrq_tmr);
-       phba->rrq_tmr.function = lpfc_rrq_timeout;
-       phba->rrq_tmr.data = (unsigned long)phba;
+       setup_timer(&phba->rrq_tmr, lpfc_rrq_timeout, (unsigned long)phba);
 
        /* FCF rediscover timer */
-       init_timer(&phba->fcf.redisc_wait);
-       phba->fcf.redisc_wait.function = lpfc_sli4_fcf_redisc_wait_tmo;
-       phba->fcf.redisc_wait.data = (unsigned long)phba;
+       setup_timer(&phba->fcf.redisc_wait, lpfc_sli4_fcf_redisc_wait_tmo,
+                       (unsigned long)phba);
 
        /*
         * Control structure for handling external multi-buffer mailbox
@@ -5706,6 +5747,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        /* Initialize the host templates with the updated values. */
        lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
        lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+       lpfc_template_no_hr.sg_tablesize = phba->cfg_sg_seg_cnt;
 
        if (phba->cfg_sg_dma_buf_size  <= LPFC_MIN_SG_SLI4_BUF_SZ)
                phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ;
@@ -5736,6 +5778,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                /* Initialize the Abort nvme buffer list used by driver */
                spin_lock_init(&phba->sli4_hba.abts_nvme_buf_list_lock);
                INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_nvme_buf_list);
+               /* Fast-path XRI aborted CQ Event work queue list */
+               INIT_LIST_HEAD(&phba->sli4_hba.sp_nvme_xri_aborted_work_queue);
        }
 
        /* This abort list used by worker thread */
@@ -5847,10 +5891,17 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                /* Check to see if it matches any module parameter */
                for (i = 0; i < lpfc_enable_nvmet_cnt; i++) {
                        if (wwn == lpfc_enable_nvmet[i]) {
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                                "6017 NVME Target %016llx\n",
                                                wwn);
                                phba->nvmet_support = 1; /* a match */
+#else
+                               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                               "6021 Can't enable NVME Target."
+                                               " NVME_TARGET_FC infrastructure"
+                                               " is not in kernel\n");
+#endif
                        }
                }
        }
@@ -8712,12 +8763,9 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                }
        }
 
-       /*
-        * Configure EQ delay multipier for interrupt coalescing using
-        * MODIFY_EQ_DELAY for all EQs created, LPFC_MAX_EQ_DELAY at a time.
-        */
-       for (qidx = 0; qidx < io_channel; qidx += LPFC_MAX_EQ_DELAY)
+       for (qidx = 0; qidx < io_channel; qidx += LPFC_MAX_EQ_DELAY_EQID_CNT)
                lpfc_modify_hba_eq_delay(phba, qidx);
+
        return 0;
 
 out_destroy:
@@ -8973,6 +9021,11 @@ lpfc_sli4_cq_event_release_all(struct lpfc_hba *phba)
        /* Pending ELS XRI abort events */
        list_splice_init(&phba->sli4_hba.sp_els_xri_aborted_work_queue,
                         &cqelist);
+       if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
+               /* Pending NVME XRI abort events */
+               list_splice_init(&phba->sli4_hba.sp_nvme_xri_aborted_work_queue,
+                                &cqelist);
+       }
        /* Pending asynnc events */
        list_splice_init(&phba->sli4_hba.sp_asynce_work_queue,
                         &cqelist);
@@ -10400,12 +10453,7 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev)
        fc_remove_host(shost);
        scsi_remove_host(shost);
 
-       /* Perform ndlp cleanup on the physical port.  The nvme and nvmet
-        * localports are destroyed after to cleanup all transport memory.
-        */
        lpfc_cleanup(vport);
-       lpfc_nvmet_destroy_targetport(phba);
-       lpfc_nvme_destroy_localport(vport);
 
        /*
         * Bring down the SLI Layer. This step disable all interrupts,
@@ -12018,6 +12066,7 @@ static struct pci_driver lpfc_driver = {
        .id_table       = lpfc_id_table,
        .probe          = lpfc_pci_probe_one,
        .remove         = lpfc_pci_remove_one,
+       .shutdown       = lpfc_pci_remove_one,
        .suspend        = lpfc_pci_suspend_one,
        .resume         = lpfc_pci_resume_one,
        .err_handler    = &lpfc_err_handler,
index c61d8d692edeeeca94512d2eeb0c2fcbdff0b382..5986c7957199df6ef97343a3c0402931cbdeb7ad 100644 (file)
@@ -646,7 +646,6 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
        }
 
        dma_buf->iocbq = lpfc_sli_get_iocbq(phba);
-       dma_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
        if (!dma_buf->iocbq) {
                kfree(dma_buf->context);
                pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
@@ -658,6 +657,7 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
                                "2621 Ran out of nvmet iocb/WQEs\n");
                return NULL;
        }
+       dma_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
        nvmewqe = dma_buf->iocbq;
        wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
        /* Initialize WQE */
index 609a908ea9db5ba291e678c296726d69cae784f9..0024de1c6c1fea8e4568007a23296dd46f709826 100644 (file)
@@ -316,7 +316,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
        bf_set(wqe_dfctl, &wqe->gen_req.wge_ctl, 0);
        bf_set(wqe_si, &wqe->gen_req.wge_ctl, 1);
        bf_set(wqe_la, &wqe->gen_req.wge_ctl, 1);
-       bf_set(wqe_rctl, &wqe->gen_req.wge_ctl, FC_RCTL_DD_UNSOL_CTL);
+       bf_set(wqe_rctl, &wqe->gen_req.wge_ctl, FC_RCTL_ELS4_REQ);
        bf_set(wqe_type, &wqe->gen_req.wge_ctl, FC_TYPE_NVME);
 
        /* Word 6 */
@@ -620,15 +620,15 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
         * Embed the payload in the last half of the WQE
         * WQE words 16-30 get the NVME CMD IU payload
         *
-        * WQE Word 16 is already setup with flags
-        * WQE words 17-19 get payload Words 2-4
+        * WQE words 16-19 get payload Words 1-4
         * WQE words 20-21 get payload Words 6-7
         * WQE words 22-29 get payload Words 16-23
         */
-       wptr = &wqe->words[17];  /* WQE ptr */
+       wptr = &wqe->words[16];  /* WQE ptr */
        dptr = (uint32_t *)nCmd->cmdaddr;  /* payload ptr */
-       dptr += 2;              /* Skip Words 0-1 in payload */
+       dptr++;                 /* Skip Word 0 in payload */
 
+       *wptr++ = *dptr++;      /* Word 1 */
        *wptr++ = *dptr++;      /* Word 2 */
        *wptr++ = *dptr++;      /* Word 3 */
        *wptr++ = *dptr++;      /* Word 4 */
@@ -978,9 +978,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
                        bf_set(wqe_cmd_type, &wqe->generic.wqe_com,
                               NVME_WRITE_CMD);
 
-                       /* Word 16 */
-                       wqe->words[16] = LPFC_NVME_EMBED_WRITE;
-
                        phba->fc4NvmeOutputRequests++;
                } else {
                        /* Word 7 */
@@ -1002,9 +999,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
                        bf_set(wqe_cmd_type, &wqe->generic.wqe_com,
                               NVME_READ_CMD);
 
-                       /* Word 16 */
-                       wqe->words[16] = LPFC_NVME_EMBED_READ;
-
                        phba->fc4NvmeInputRequests++;
                }
        } else {
@@ -1026,9 +1020,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
                /* Word 11 */
                bf_set(wqe_cmd_type, &wqe->generic.wqe_com, NVME_READ_CMD);
 
-               /* Word 16 */
-               wqe->words[16] = LPFC_NVME_EMBED_CMD;
-
                phba->fc4NvmeControlRequests++;
        }
        /*
@@ -1286,6 +1277,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
        pnvme_fcreq->private = (void *)lpfc_ncmd;
        lpfc_ncmd->nvmeCmd = pnvme_fcreq;
        lpfc_ncmd->nrport = rport;
+       lpfc_ncmd->ndlp = ndlp;
        lpfc_ncmd->start_time = jiffies;
 
        lpfc_nvme_prep_io_cmd(vport, lpfc_ncmd, ndlp);
@@ -1319,7 +1311,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
                                 "sid: x%x did: x%x oxid: x%x\n",
                                 ret, vport->fc_myDID, ndlp->nlp_DID,
                                 lpfc_ncmd->cur_iocbq.sli4_xritag);
-               ret = -EINVAL;
+               ret = -EBUSY;
                goto out_free_nvme_buf;
        }
 
@@ -1821,10 +1813,10 @@ lpfc_post_nvme_sgl_list(struct lpfc_hba *phba,
                                                pdma_phys_sgl1, cur_xritag);
                                if (status) {
                                        /* failure, put on abort nvme list */
-                                       lpfc_ncmd->exch_busy = 1;
+                                       lpfc_ncmd->flags |= LPFC_SBUF_XBUSY;
                                } else {
                                        /* success, put on NVME buffer list */
-                                       lpfc_ncmd->exch_busy = 0;
+                                       lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
                                        lpfc_ncmd->status = IOSTAT_SUCCESS;
                                        num_posted++;
                                }
@@ -1854,10 +1846,10 @@ lpfc_post_nvme_sgl_list(struct lpfc_hba *phba,
                                         struct lpfc_nvme_buf, list);
                        if (status) {
                                /* failure, put on abort nvme list */
-                               lpfc_ncmd->exch_busy = 1;
+                               lpfc_ncmd->flags |= LPFC_SBUF_XBUSY;
                        } else {
                                /* success, put on NVME buffer list */
-                               lpfc_ncmd->exch_busy = 0;
+                               lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
                                lpfc_ncmd->status = IOSTAT_SUCCESS;
                                num_posted++;
                        }
@@ -2099,7 +2091,7 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_nvme_buf *lpfc_ncmd)
        unsigned long iflag = 0;
 
        lpfc_ncmd->nonsg_phys = 0;
-       if (lpfc_ncmd->exch_busy) {
+       if (lpfc_ncmd->flags & LPFC_SBUF_XBUSY) {
                spin_lock_irqsave(&phba->sli4_hba.abts_nvme_buf_list_lock,
                                        iflag);
                lpfc_ncmd->nvmeCmd = NULL;
@@ -2135,11 +2127,12 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_nvme_buf *lpfc_ncmd)
 int
 lpfc_nvme_create_localport(struct lpfc_vport *vport)
 {
+       int ret = 0;
        struct lpfc_hba  *phba = vport->phba;
        struct nvme_fc_port_info nfcp_info;
        struct nvme_fc_local_port *localport;
        struct lpfc_nvme_lport *lport;
-       int len, ret = 0;
+       int len;
 
        /* Initialize this localport instance.  The vport wwn usage ensures
         * that NPIV is accounted for.
@@ -2156,8 +2149,12 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
        /* localport is allocated from the stack, but the registration
         * call allocates heap memory as well as the private area.
         */
+#if (IS_ENABLED(CONFIG_NVME_FC))
        ret = nvme_fc_register_localport(&nfcp_info, &lpfc_nvme_template,
                                         &vport->phba->pcidev->dev, &localport);
+#else
+       ret = -ENOMEM;
+#endif
        if (!ret) {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME | LOG_NVME_DISC,
                                 "6005 Successfully registered local "
@@ -2173,10 +2170,10 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
                lport->vport = vport;
                INIT_LIST_HEAD(&lport->rport_list);
                vport->nvmei_support = 1;
+               len  = lpfc_new_nvme_buf(vport, phba->sli4_hba.nvme_xri_max);
+               vport->phba->total_nvme_bufs += len;
        }
 
-       len  = lpfc_new_nvme_buf(vport, phba->sli4_hba.nvme_xri_max);
-       vport->phba->total_nvme_bufs += len;
        return ret;
 }
 
@@ -2193,6 +2190,7 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
 void
 lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
 {
+#if (IS_ENABLED(CONFIG_NVME_FC))
        struct nvme_fc_local_port *localport;
        struct lpfc_nvme_lport *lport;
        struct lpfc_nvme_rport *rport = NULL, *rport_next = NULL;
@@ -2208,7 +2206,6 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME,
                         "6011 Destroying NVME localport %p\n",
                         localport);
-
        list_for_each_entry_safe(rport, rport_next, &lport->rport_list, list) {
                /* The last node ref has to get released now before the rport
                 * private memory area is released by the transport.
@@ -2222,6 +2219,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
                                         "6008 rport fail destroy %x\n", ret);
                wait_for_completion_timeout(&rport->rport_unreg_done, 5);
        }
+
        /* lport's rport list is clear.  Unregister
         * lport and release resources.
         */
@@ -2245,6 +2243,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
                                 "Failed, status x%x\n",
                                 ret);
        }
+#endif
 }
 
 void
@@ -2275,6 +2274,7 @@ lpfc_nvme_update_localport(struct lpfc_vport *vport)
 int
 lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
+#if (IS_ENABLED(CONFIG_NVME_FC))
        int ret = 0;
        struct nvme_fc_local_port *localport;
        struct lpfc_nvme_lport *lport;
@@ -2348,7 +2348,6 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                        rpinfo.port_role |= FC_PORT_ROLE_NVME_INITIATOR;
                rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
                rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
-
                ret = nvme_fc_register_remoteport(localport, &rpinfo,
                                                  &remote_port);
                if (!ret) {
@@ -2384,6 +2383,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                                 ndlp->nlp_type, ndlp->nlp_DID, ndlp);
        }
        return ret;
+#else
+       return 0;
+#endif
 }
 
 /* lpfc_nvme_unregister_port - unbind the DID and port_role from this rport.
@@ -2401,6 +2403,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 void
 lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
+#if (IS_ENABLED(CONFIG_NVME_FC))
        int ret;
        struct nvme_fc_local_port *localport;
        struct lpfc_nvme_lport *lport;
@@ -2458,7 +2461,61 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
        return;
 
  input_err:
+#endif
        lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
                         "6168: State error: lport %p, rport%p FCID x%06x\n",
                         vport->localport, ndlp->rport, ndlp->nlp_DID);
 }
+
+/**
+ * lpfc_sli4_nvme_xri_aborted - Fast-path process of NVME xri abort
+ * @phba: pointer to lpfc hba data structure.
+ * @axri: pointer to the fcp xri abort wcqe structure.
+ *
+ * This routine is invoked by the worker thread to process a SLI4 fast-path
+ * FCP aborted xri.
+ **/
+void
+lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
+                          struct sli4_wcqe_xri_aborted *axri)
+{
+       uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
+       uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
+       struct lpfc_nvme_buf *lpfc_ncmd, *next_lpfc_ncmd;
+       struct lpfc_nodelist *ndlp;
+       unsigned long iflag = 0;
+       int rrq_empty = 0;
+
+       if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
+               return;
+       spin_lock_irqsave(&phba->hbalock, iflag);
+       spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock);
+       list_for_each_entry_safe(lpfc_ncmd, next_lpfc_ncmd,
+                                &phba->sli4_hba.lpfc_abts_nvme_buf_list,
+                                list) {
+               if (lpfc_ncmd->cur_iocbq.sli4_xritag == xri) {
+                       list_del(&lpfc_ncmd->list);
+                       lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
+                       lpfc_ncmd->status = IOSTAT_SUCCESS;
+                       spin_unlock(
+                               &phba->sli4_hba.abts_nvme_buf_list_lock);
+
+                       rrq_empty = list_empty(&phba->active_rrq_list);
+                       spin_unlock_irqrestore(&phba->hbalock, iflag);
+                       ndlp = lpfc_ncmd->ndlp;
+                       if (ndlp) {
+                               lpfc_set_rrq_active(
+                                       phba, ndlp,
+                                       lpfc_ncmd->cur_iocbq.sli4_lxritag,
+                                       rxid, 1);
+                               lpfc_sli4_abts_err_handler(phba, ndlp, axri);
+                       }
+                       lpfc_release_nvme_buf(phba, lpfc_ncmd);
+                       if (rrq_empty)
+                               lpfc_worker_wake_up(phba);
+                       return;
+               }
+       }
+       spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
+       spin_unlock_irqrestore(&phba->hbalock, iflag);
+}
index b2fae5e813f8a82b17b53a5cd5affd8f7e5d6bad..1347deb8dd6cbd3e56db9f615cbc55e8290fc443 100644 (file)
@@ -57,6 +57,7 @@ struct lpfc_nvme_buf {
        struct list_head list;
        struct nvmefc_fcp_req *nvmeCmd;
        struct lpfc_nvme_rport *nrport;
+       struct lpfc_nodelist *ndlp;
 
        uint32_t timeout;
 
index c421e1738ee989efcca922da9b145995cc164c72..7ca868f394da62db293701af58b6797687eea89b 100644 (file)
@@ -571,6 +571,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
                                "6102 Bad state IO x%x aborted\n",
                                ctxp->oxid);
+               rc = -ENXIO;
                goto aerr;
        }
 
@@ -580,6 +581,7 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
                                "6152 FCP Drop IO x%x: Prep\n",
                                ctxp->oxid);
+               rc = -ENXIO;
                goto aerr;
        }
 
@@ -618,8 +620,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
        ctxp->wqeq->hba_wqidx = 0;
        nvmewqeq->context2 = NULL;
        nvmewqeq->context3 = NULL;
+       rc = -EBUSY;
 aerr:
-       return -ENXIO;
+       return rc;
 }
 
 static void
@@ -668,9 +671,13 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
        lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP |
                                           NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED;
 
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
        error = nvmet_fc_register_targetport(&pinfo, &lpfc_tgttemplate,
                                             &phba->pcidev->dev,
                                             &phba->targetport);
+#else
+       error = -ENOMEM;
+#endif
        if (error) {
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
                                "6025 Cannot register NVME targetport "
@@ -731,9 +738,25 @@ lpfc_nvmet_update_targetport(struct lpfc_hba *phba)
        return 0;
 }
 
+/**
+ * lpfc_sli4_nvmet_xri_aborted - Fast-path process of nvmet xri abort
+ * @phba: pointer to lpfc hba data structure.
+ * @axri: pointer to the nvmet xri abort wcqe structure.
+ *
+ * This routine is invoked by the worker thread to process a SLI4 fast-path
+ * NVMET aborted xri.
+ **/
+void
+lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
+                           struct sli4_wcqe_xri_aborted *axri)
+{
+       /* TODO: work in progress */
+}
+
 void
 lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
 {
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
        struct lpfc_nvmet_tgtport *tgtp;
 
        if (phba->nvmet_support == 0)
@@ -745,6 +768,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
                wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
        }
        phba->targetport = NULL;
+#endif
 }
 
 /**
@@ -764,6 +788,7 @@ static void
 lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                           struct hbq_dmabuf *nvmebuf)
 {
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
        struct lpfc_nvmet_tgtport *tgtp;
        struct fc_frame_header *fc_hdr;
        struct lpfc_nvmet_rcv_ctx *ctxp;
@@ -844,6 +869,7 @@ dropit:
 
        atomic_inc(&tgtp->xmt_ls_abort);
        lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, sid, oxid);
+#endif
 }
 
 /**
@@ -865,6 +891,7 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
                            struct rqb_dmabuf *nvmebuf,
                            uint64_t isr_timestamp)
 {
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
        struct lpfc_nvmet_rcv_ctx *ctxp;
        struct lpfc_nvmet_tgtport *tgtp;
        struct fc_frame_header *fc_hdr;
@@ -955,7 +982,7 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
 
        atomic_inc(&tgtp->rcv_fcp_cmd_drop);
        lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
-                       "6159 FCP Drop IO x%x: nvmet_fc_rcv_fcp_req x%x\n",
+                       "6159 FCP Drop IO x%x: err x%x\n",
                        ctxp->oxid, rc);
 dropit:
        lpfc_nvmeio_data(phba, "NVMET FCP DROP: xri x%x sz %d from %06x\n",
@@ -970,6 +997,7 @@ dropit:
                /* We assume a rcv'ed cmd ALWAYs fits into 1 buffer */
                lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
        }
+#endif
 }
 
 /**
@@ -1114,7 +1142,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba,
        bf_set(wqe_dfctl, &wqe->xmit_sequence.wge_ctl, 0);
        bf_set(wqe_ls, &wqe->xmit_sequence.wge_ctl, 1);
        bf_set(wqe_la, &wqe->xmit_sequence.wge_ctl, 0);
-       bf_set(wqe_rctl, &wqe->xmit_sequence.wge_ctl, FC_RCTL_DD_SOL_CTL);
+       bf_set(wqe_rctl, &wqe->xmit_sequence.wge_ctl, FC_RCTL_ELS4_REP);
        bf_set(wqe_type, &wqe->xmit_sequence.wge_ctl, FC_TYPE_NVME);
 
        /* Word 6 */
@@ -1445,7 +1473,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
 
        case NVMET_FCOP_RSP:
                /* Words 0 - 2 */
-               sgel = &rsp->sg[0];
                physaddr = rsp->rspdma;
                wqe->fcp_trsp.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
                wqe->fcp_trsp.bde.tus.f.bdeSize = rsp->rsplen;
@@ -1681,8 +1708,8 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
        struct lpfc_nodelist *ndlp;
 
        lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
-                       "6067 %s: Entrypoint: sid %x xri %x\n", __func__,
-                       sid, xri);
+                       "6067 Abort: sid %x xri x%x/x%x\n",
+                       sid, xri, ctxp->wqeq->sli4_xritag);
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
 
@@ -1693,7 +1720,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
                atomic_inc(&tgtp->xmt_abort_rsp_error);
                lpfc_printf_log(phba, KERN_WARNING, LOG_NVME_ABTS,
                                "6134 Drop ABTS - wrong NDLP state x%x.\n",
-                               ndlp->nlp_state);
+                               (ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE);
 
                /* No failure to an ABTS request. */
                return 0;
@@ -1791,7 +1818,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
                atomic_inc(&tgtp->xmt_abort_rsp_error);
                lpfc_printf_log(phba, KERN_WARNING, LOG_NVME_ABTS,
                                "6160 Drop ABTS - wrong NDLP state x%x.\n",
-                               ndlp->nlp_state);
+                               (ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE);
 
                /* No failure to an ABTS request. */
                return 0;
index 9d6384af9fce7e9b321e8031a421869095fbab55..54fd0c81ceaf69a7ceb475acb87e309df7e10de1 100644 (file)
@@ -5953,12 +5953,13 @@ struct scsi_host_template lpfc_template_nvme = {
        .track_queue_depth      = 0,
 };
 
-struct scsi_host_template lpfc_template_s3 = {
+struct scsi_host_template lpfc_template_no_hr = {
        .module                 = THIS_MODULE,
        .name                   = LPFC_DRIVER_NAME,
        .proc_name              = LPFC_DRIVER_NAME,
        .info                   = lpfc_info,
        .queuecommand           = lpfc_queuecommand,
+       .eh_timed_out           = fc_eh_timed_out,
        .eh_abort_handler       = lpfc_abort_handler,
        .eh_device_reset_handler = lpfc_device_reset_handler,
        .eh_target_reset_handler = lpfc_target_reset_handler,
@@ -6015,7 +6016,6 @@ struct scsi_host_template lpfc_vport_template = {
        .eh_abort_handler       = lpfc_abort_handler,
        .eh_device_reset_handler = lpfc_device_reset_handler,
        .eh_target_reset_handler = lpfc_target_reset_handler,
-       .eh_bus_reset_handler   = lpfc_bus_reset_handler,
        .slave_alloc            = lpfc_slave_alloc,
        .slave_configure        = lpfc_slave_configure,
        .slave_destroy          = lpfc_slave_destroy,
index e43e5e23c24b475f3f8930bcae9cb67e4685153e..1c9fa45df7eb5deec4c8988b18ffe36f4621b267 100644 (file)
@@ -1,3 +1,4 @@
+
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
@@ -952,7 +953,7 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
        start_sglq = sglq;
        while (!found) {
                if (!sglq)
-                       return NULL;
+                       break;
                if (ndlp && ndlp->active_rrqs_xri_bitmap &&
                    test_bit(sglq->sli4_lxritag,
                    ndlp->active_rrqs_xri_bitmap)) {
@@ -12212,6 +12213,41 @@ void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *phba)
        }
 }
 
+/**
+ * lpfc_sli4_nvme_xri_abort_event_proc - Process nvme xri abort event
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked by the worker thread to process all the pending
+ * SLI4 NVME abort XRI events.
+ **/
+void lpfc_sli4_nvme_xri_abort_event_proc(struct lpfc_hba *phba)
+{
+       struct lpfc_cq_event *cq_event;
+
+       /* First, declare the fcp xri abort event has been handled */
+       spin_lock_irq(&phba->hbalock);
+       phba->hba_flag &= ~NVME_XRI_ABORT_EVENT;
+       spin_unlock_irq(&phba->hbalock);
+       /* Now, handle all the fcp xri abort events */
+       while (!list_empty(&phba->sli4_hba.sp_nvme_xri_aborted_work_queue)) {
+               /* Get the first event from the head of the event queue */
+               spin_lock_irq(&phba->hbalock);
+               list_remove_head(&phba->sli4_hba.sp_nvme_xri_aborted_work_queue,
+                                cq_event, struct lpfc_cq_event, list);
+               spin_unlock_irq(&phba->hbalock);
+               /* Notify aborted XRI for NVME work queue */
+               if (phba->nvmet_support) {
+                       lpfc_sli4_nvmet_xri_aborted(phba,
+                                                   &cq_event->cqe.wcqe_axri);
+               } else {
+                       lpfc_sli4_nvme_xri_aborted(phba,
+                                                  &cq_event->cqe.wcqe_axri);
+               }
+               /* Free the event processed back to the free pool */
+               lpfc_sli4_cq_event_release(phba, cq_event);
+       }
+}
+
 /**
  * lpfc_sli4_els_xri_abort_event_proc - Process els xri abort event
  * @phba: pointer to lpfc hba data structure.
@@ -12709,10 +12745,22 @@ lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba,
                spin_unlock_irqrestore(&phba->hbalock, iflags);
                workposted = true;
                break;
+       case LPFC_NVME:
+               spin_lock_irqsave(&phba->hbalock, iflags);
+               list_add_tail(&cq_event->list,
+                             &phba->sli4_hba.sp_nvme_xri_aborted_work_queue);
+               /* Set the nvme xri abort event flag */
+               phba->hba_flag |= NVME_XRI_ABORT_EVENT;
+               spin_unlock_irqrestore(&phba->hbalock, iflags);
+               workposted = true;
+               break;
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "0603 Invalid work queue CQE subtype (x%x)\n",
-                               cq->subtype);
+                               "0603 Invalid CQ subtype %d: "
+                               "%08x %08x %08x %08x\n",
+                               cq->subtype, wcqe->word0, wcqe->parameter,
+                               wcqe->word2, wcqe->word3);
+               lpfc_sli4_cq_event_release(phba, cq_event);
                workposted = false;
                break;
        }
@@ -13827,6 +13875,8 @@ lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
  * @startq: The starting FCP EQ to modify
  *
  * This function sends an MODIFY_EQ_DELAY mailbox command to the HBA.
+ * The command allows up to LPFC_MAX_EQ_DELAY_EQID_CNT EQ ID's to be
+ * updated in one mailbox command.
  *
  * The @phba struct is used to send mailbox command to HBA. The @startq
  * is used to get the starting FCP EQ to change.
@@ -13879,7 +13929,7 @@ lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq)
                eq_delay->u.request.eq[cnt].phase = 0;
                eq_delay->u.request.eq[cnt].delay_multi = dmult;
                cnt++;
-               if (cnt >= LPFC_MAX_EQ_DELAY)
+               if (cnt >= LPFC_MAX_EQ_DELAY_EQID_CNT)
                        break;
        }
        eq_delay->u.request.num_eq = cnt;
@@ -15185,17 +15235,17 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
                drq = drqp[idx];
                cq  = cqp[idx];
 
-               if (hrq->entry_count != drq->entry_count) {
-                       status = -EINVAL;
-                       goto out;
-               }
-
                /* sanity check on queue memory */
                if (!hrq || !drq || !cq) {
                        status = -ENODEV;
                        goto out;
                }
 
+               if (hrq->entry_count != drq->entry_count) {
+                       status = -EINVAL;
+                       goto out;
+               }
+
                if (idx == 0) {
                        bf_set(lpfc_mbx_rq_create_num_pages,
                               &rq_create->u.request,
index 91153c9f6d18259b3978b7f3218ad76198170c34..710458cf11d62f77c7a48973aded3f255b233277 100644 (file)
@@ -642,6 +642,7 @@ struct lpfc_sli4_hba {
        struct list_head sp_asynce_work_queue;
        struct list_head sp_fcp_xri_aborted_work_queue;
        struct list_head sp_els_xri_aborted_work_queue;
+       struct list_head sp_nvme_xri_aborted_work_queue;
        struct list_head sp_unsol_work_queue;
        struct lpfc_sli4_link link_state;
        struct lpfc_sli4_lnk_info lnk_info;
@@ -794,9 +795,14 @@ void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);
 int lpfc_sli4_resume_rpi(struct lpfc_nodelist *,
                        void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *);
 void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *);
+void lpfc_sli4_nvme_xri_abort_event_proc(struct lpfc_hba *phba);
 void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *);
 void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *,
                               struct sli4_wcqe_xri_aborted *);
+void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
+                               struct sli4_wcqe_xri_aborted *axri);
+void lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
+                                struct sli4_wcqe_xri_aborted *axri);
 void lpfc_sli4_els_xri_aborted(struct lpfc_hba *,
                               struct sli4_wcqe_xri_aborted *);
 void lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *);
index 86c6c9b26b823a04dd5afbdff4688901d577c82d..d4e95e28f4e3d55a6ec97162cfdb1e26998e4fe1 100644 (file)
@@ -20,7 +20,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "11.2.0.7"
+#define LPFC_DRIVER_VERSION "11.2.0.10"
 #define LPFC_DRIVER_NAME               "lpfc"
 
 /* Used for SLI 2/3 */
index e7e5974e1a2c435ef2ee0a79276e981fcb79cc87..2b209bbb4c9165fa7afdeff0f233f649684f8495 100644 (file)
@@ -35,8 +35,8 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "07.701.16.00-rc1"
-#define MEGASAS_RELDATE                                "February 2, 2017"
+#define MEGASAS_VERSION                                "07.701.17.00-rc1"
+#define MEGASAS_RELDATE                                "March 2, 2017"
 
 /*
  * Device IDs
index 7ac9a9ee9bd473c3cc0b6178975f46e3d32f3b77..0016f12cc563e7c6e1eb3c2a87685f60c83b9747 100644 (file)
@@ -1963,6 +1963,9 @@ scan_target:
        if (!mr_device_priv_data)
                return -ENOMEM;
        sdev->hostdata = mr_device_priv_data;
+
+       atomic_set(&mr_device_priv_data->r1_ldio_hint,
+                  instance->r1_ldio_hint_default);
        return 0;
 }
 
@@ -5034,10 +5037,12 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe)
                                         &instance->irq_context[j]);
                        /* Retry irq register for IO_APIC*/
                        instance->msix_vectors = 0;
-                       if (is_probe)
+                       if (is_probe) {
+                               pci_free_irq_vectors(instance->pdev);
                                return megasas_setup_irqs_ioapic(instance);
-                       else
+                       } else {
                                return -1;
+                       }
                }
        }
        return 0;
@@ -5277,9 +5282,11 @@ static int megasas_init_fw(struct megasas_instance *instance)
                        MPI2_REPLY_POST_HOST_INDEX_OFFSET);
        }
 
-       i = pci_alloc_irq_vectors(instance->pdev, 1, 1, PCI_IRQ_LEGACY);
-       if (i < 0)
-               goto fail_setup_irqs;
+       if (!instance->msix_vectors) {
+               i = pci_alloc_irq_vectors(instance->pdev, 1, 1, PCI_IRQ_LEGACY);
+               if (i < 0)
+                       goto fail_setup_irqs;
+       }
 
        dev_info(&instance->pdev->dev,
                "firmware supports msix\t: (%d)", fw_msix_count);
index 29650ba669da58da099cf91e9de0aae504146bb0..f990ab4d45e1bf72b3adf8991b11c01309c7530b 100644 (file)
@@ -2159,7 +2159,7 @@ megasas_set_raidflag_cpu_affinity(union RAID_CONTEXT_UNION *praid_context,
                                cpu_sel = MR_RAID_CTX_CPUSEL_1;
 
                        if (is_stream_detected(rctx_g35) &&
-                           (raid->level == 5) &&
+                           ((raid->level == 5) || (raid->level == 6)) &&
                            (raid->writeMode == MR_RL_WRITE_THROUGH_MODE) &&
                            (cpu_sel == MR_RAID_CTX_CPUSEL_FCFS))
                                cpu_sel = MR_RAID_CTX_CPUSEL_0;
@@ -2338,7 +2338,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                                fp_possible = false;
                                atomic_dec(&instance->fw_outstanding);
                        } else if ((scsi_buff_len > MR_LARGE_IO_MIN_SIZE) ||
-                                  atomic_dec_if_positive(&mrdev_priv->r1_ldio_hint)) {
+                                  (atomic_dec_if_positive(&mrdev_priv->r1_ldio_hint) > 0)) {
                                fp_possible = false;
                                atomic_dec(&instance->fw_outstanding);
                                if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE)
index 7fe7e6ed595b79e8831bfbeb55767e5d65ff7e5c..8981806fb13fa7792e2b8d45f4fc6880b362da25 100644 (file)
@@ -1442,9 +1442,6 @@ void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
        u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
 extern struct sas_function_template mpt3sas_transport_functions;
 extern struct scsi_transport_template *mpt3sas_transport_template;
-extern int scsi_internal_device_block(struct scsi_device *sdev);
-extern int scsi_internal_device_unblock(struct scsi_device *sdev,
-                               enum scsi_device_state new_state);
 /* trigger data externs */
 void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
        struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
index 46e866c36c8a884a98588a8d7a81272aed0ce400..919ba2bb15f110f4619a72646d170f87ad985237 100644 (file)
@@ -2859,7 +2859,7 @@ _scsih_internal_device_block(struct scsi_device *sdev,
            sas_device_priv_data->sas_target->handle);
        sas_device_priv_data->block = 1;
 
-       r = scsi_internal_device_block(sdev);
+       r = scsi_internal_device_block(sdev, false);
        if (r == -EINVAL)
                sdev_printk(KERN_WARNING, sdev,
                    "device_block failed with return(%d) for handle(0x%04x)\n",
@@ -2895,7 +2895,7 @@ _scsih_internal_device_unblock(struct scsi_device *sdev,
                    "performing a block followed by an unblock\n",
                    r, sas_device_priv_data->sas_target->handle);
                sas_device_priv_data->block = 1;
-               r = scsi_internal_device_block(sdev);
+               r = scsi_internal_device_block(sdev, false);
                if (r)
                        sdev_printk(KERN_WARNING, sdev, "retried device_block "
                            "failed with return(%d) for handle(0x%04x)\n",
@@ -4677,7 +4677,6 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        u32 response_code = 0;
        unsigned long flags;
-       unsigned int sector_sz;
 
        mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
 
@@ -4742,20 +4741,6 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        }
 
        xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
-
-       /* In case of bogus fw or device, we could end up having
-        * unaligned partial completion. We can force alignment here,
-        * then scsi-ml does not need to handle this misbehavior.
-        */
-       sector_sz = scmd->device->sector_size;
-       if (unlikely(!blk_rq_is_passthrough(scmd->request) && sector_sz &&
-                    xfer_cnt % sector_sz)) {
-               sdev_printk(KERN_INFO, scmd->device,
-                   "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
-                           xfer_cnt, sector_sz);
-               xfer_cnt = round_down(xfer_cnt, sector_sz);
-       }
-
        scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
        if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
                log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
index 23bd70628a2f05b9c5a5c2dbd6184e4ad6d076b2..7d173f48a81e8d240cd5d957b2997a3c0c3f0223 100644 (file)
@@ -81,14 +81,17 @@ struct qedf_dbg_ctx {
 #define QEDF_INFO(pdev, level, fmt, ...)       \
                qedf_dbg_info(pdev, __func__, __LINE__, level, fmt,     \
                              ## __VA_ARGS__)
-
-extern void qedf_dbg_err(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
+__printf(4, 5)
+void qedf_dbg_err(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
                          const char *fmt, ...);
-extern void qedf_dbg_warn(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
+__printf(4, 5)
+void qedf_dbg_warn(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
                           const char *, ...);
-extern void qedf_dbg_notice(struct qedf_dbg_ctx *qedf, const char *func,
+__printf(4, 5)
+void qedf_dbg_notice(struct qedf_dbg_ctx *qedf, const char *func,
                            u32 line, const char *, ...);
-extern void qedf_dbg_info(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
+__printf(5, 6)
+void qedf_dbg_info(struct qedf_dbg_ctx *qedf, const char *func, u32 line,
                          u32 info, const char *fmt, ...);
 
 /* GRC Dump related defines */
index 868d423380d120ca82c135a8e545fbd98e1ba935..ed58b9104f58b8894b3dfd924c6facfaba29be67 100644 (file)
@@ -203,7 +203,7 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
                        case FIP_DT_MAC:
                                mp = (struct fip_mac_desc *)desc;
                                QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
-                                   "fd_mac=%pM.\n", __func__, mp->fd_mac);
+                                   "fd_mac=%pM\n", mp->fd_mac);
                                ether_addr_copy(cvl_mac, mp->fd_mac);
                                break;
                        case FIP_DT_NAME:
index ee0dcf9d3aba7847eaa673ab3542a1c0d6d375c3..46debe5034af102710a574a80254433b94265271 100644 (file)
@@ -1342,7 +1342,7 @@ void qedf_scsi_completion(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
                } else {
                        refcount = kref_read(&io_req->refcount);
                        QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO,
-                           "%d:0:%d:%d xid=0x%0x op=0x%02x "
+                           "%d:0:%d:%lld xid=0x%0x op=0x%02x "
                            "lba=%02x%02x%02x%02x cdb_status=%d "
                            "fcp_resid=0x%x refcount=%d.\n",
                            qedf->lport->host->host_no, sc_cmd->device->id,
@@ -1426,7 +1426,7 @@ void qedf_scsi_done(struct qedf_ctx *qedf, struct qedf_ioreq *io_req,
 
        sc_cmd->result = result << 16;
        refcount = kref_read(&io_req->refcount);
-       QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO, "%d:0:%d:%d: Completing "
+       QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO, "%d:0:%d:%lld: Completing "
            "sc_cmd=%p result=0x%08x op=0x%02x lba=0x%02x%02x%02x%02x, "
            "allowed=%d retries=%d refcount=%d.\n",
            qedf->lport->host->host_no, sc_cmd->device->id,
index d9d7a86b5f8baf13038cfc1bd17885945d1fdf4e..8e2a160490e66a747e75bf9c0c1a149e34d474a3 100644 (file)
@@ -2456,8 +2456,8 @@ static int qedf_alloc_bdq(struct qedf_ctx *qedf)
        }
 
        QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
-           "BDQ PBL addr=0x%p dma=0x%llx.\n", qedf->bdq_pbl,
-           qedf->bdq_pbl_dma);
+                 "BDQ PBL addr=0x%p dma=%pad\n",
+                 qedf->bdq_pbl, &qedf->bdq_pbl_dma);
 
        /*
         * Populate BDQ PBL with physical and virtual address of individual
index 955936274241406e2c8df92a7f3a5fcd530d7f05..59417199bf363ae956bb2832f10fe22307a978d1 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/debugfs.h>
 #include <linux/module.h>
 
-int do_not_recover;
+int qedi_do_not_recover;
 static struct dentry *qedi_dbg_root;
 
 void
@@ -74,22 +74,22 @@ qedi_dbg_exit(void)
 static ssize_t
 qedi_dbg_do_not_recover_enable(struct qedi_dbg_ctx *qedi_dbg)
 {
-       if (!do_not_recover)
-               do_not_recover = 1;
+       if (!qedi_do_not_recover)
+               qedi_do_not_recover = 1;
 
        QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n",
-                 do_not_recover);
+                 qedi_do_not_recover);
        return 0;
 }
 
 static ssize_t
 qedi_dbg_do_not_recover_disable(struct qedi_dbg_ctx *qedi_dbg)
 {
-       if (do_not_recover)
-               do_not_recover = 0;
+       if (qedi_do_not_recover)
+               qedi_do_not_recover = 0;
 
        QEDI_INFO(qedi_dbg, QEDI_LOG_DEBUGFS, "do_not_recover=%d\n",
-                 do_not_recover);
+                 qedi_do_not_recover);
        return 0;
 }
 
@@ -141,7 +141,7 @@ qedi_dbg_do_not_recover_cmd_read(struct file *filp, char __user *buffer,
        if (*ppos)
                return 0;
 
-       cnt = sprintf(buffer, "do_not_recover=%d\n", do_not_recover);
+       cnt = sprintf(buffer, "do_not_recover=%d\n", qedi_do_not_recover);
        cnt = min_t(int, count, cnt - *ppos);
        *ppos += cnt;
        return cnt;
index c9f0ef4e11b33ce9ca2a707645b1b2088b6a1f63..2bce3efc66a4b4bda8bae40768ca3e961a6d33b0 100644 (file)
@@ -1461,9 +1461,9 @@ static void qedi_tmf_work(struct work_struct *work)
                  get_itt(tmf_hdr->rtt), get_itt(ctask->itt), cmd->task_id,
                  qedi_conn->iscsi_conn_id);
 
-       if (do_not_recover) {
+       if (qedi_do_not_recover) {
                QEDI_ERR(&qedi->dbg_ctx, "DONT SEND CLEANUP/ABORT %d\n",
-                        do_not_recover);
+                        qedi_do_not_recover);
                goto abort_ret;
        }
 
index 8e488de88ece9fb8fc49b991935cf5c24a87b5b4..63d793f460645d44c4ae29638145cbcbcbc9be78 100644 (file)
 
 #include "qedi_iscsi.h"
 
+#ifdef CONFIG_DEBUG_FS
+extern int qedi_do_not_recover;
+#else
+#define qedi_do_not_recover (0)
+#endif
+
 extern uint qedi_io_tracing;
-extern int do_not_recover;
+
 extern struct scsi_host_template qedi_host_template;
 extern struct iscsi_transport qedi_iscsi_transport;
 extern const struct qed_iscsi_ops *qedi_ops;
index b9f79d36142d5e85182d39d16ba34a7a1a6f6521..4cc474364c50568806b16520ddd66239b9f3ebfd 100644 (file)
@@ -833,7 +833,7 @@ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
                return ERR_PTR(ret);
        }
 
-       if (do_not_recover) {
+       if (qedi_do_not_recover) {
                ret = -ENOMEM;
                return ERR_PTR(ret);
        }
@@ -957,7 +957,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
        struct qedi_endpoint *qedi_ep;
        int ret = 0;
 
-       if (do_not_recover)
+       if (qedi_do_not_recover)
                return 1;
 
        qedi_ep = ep->dd_data;
@@ -1025,7 +1025,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
                }
 
                if (test_bit(QEDI_IN_RECOVERY, &qedi->flags)) {
-                       if (do_not_recover) {
+                       if (qedi_do_not_recover) {
                                QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
                                          "Do not recover cid=0x%x\n",
                                          qedi_ep->iscsi_cid);
@@ -1039,7 +1039,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
                }
        }
 
-       if (do_not_recover)
+       if (qedi_do_not_recover)
                goto ep_exit_recover;
 
        switch (qedi_ep->state) {
index 5eda21d903e93dfc96702552d2de9deb7f01c734..8e3d92807cb8033acea1bc3c9e990b05f521f8a8 100644 (file)
@@ -1805,7 +1805,7 @@ static int __qedi_probe(struct pci_dev *pdev, int mode)
         */
        qedi_ops->common->update_pf_params(qedi->cdev, &qedi->pf_params);
 
-       qedi_setup_int(qedi);
+       rc = qedi_setup_int(qedi);
        if (rc)
                goto stop_iscsi_func;
 
index 67c0d5aa32125ca135ccb6cc2bd83af76b0ffd1b..de952935b5d2ca572d618e2a8802a1e035c0fbdb 100644 (file)
@@ -3,6 +3,7 @@ config SCSI_QLA_FC
        depends on PCI && SCSI
        depends on SCSI_FC_ATTRS
        select FW_LOADER
+       select BTREE
        ---help---
        This qla2xxx driver supports all QLogic Fibre Channel
        PCI and PCIe host adapters.
index f610103994afd4c53cbf439db646eb5b44851689..435ff7fd6384a0a4e941efb3d60411e0731d4c1b 100644 (file)
@@ -2154,8 +2154,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
                    "Timer for the VP[%d] has stopped\n", vha->vp_idx);
        }
 
-       BUG_ON(atomic_read(&vha->vref_count));
-
        qla2x00_free_fcports(vha);
 
        mutex_lock(&ha->vport_lock);
@@ -2166,7 +2164,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
        dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
            vha->gnl.ldma);
 
-       if (vha->qpair->vp_idx == vha->vp_idx) {
+       if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
                if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
                        ql_log(ql_log_warn, vha, 0x7087,
                            "Queue Pair delete failed.\n");
index 21d9fb7fc88796cbaa09fbfa160b9b20c17e2015..51b4179469d1851be96872ee39b24739fc34135e 100644 (file)
@@ -2707,13 +2707,9 @@ ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
            "%-+5d  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n", size);
        ql_dbg(level, vha, id,
            "----- -----------------------------------------------\n");
-       for (cnt = 0; cnt < size; cnt++, buf++) {
-               if (cnt % 16 == 0)
-                       ql_dbg(level, vha, id, "%04x:", cnt & ~0xFU);
-               printk(" %02x", *buf);
-               if (cnt % 16 == 15)
-                       printk("\n");
+       for (cnt = 0; cnt < size; cnt += 16) {
+               ql_dbg(level, vha, id, "%04x: ", cnt);
+               print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+                              buf + cnt, min(16U, size - cnt), false);
        }
-       if (cnt % 16 != 0)
-               printk("\n");
 }
index e1fc4e66966aeab7b64bfd4ca9c75ca4da1a5be5..c6bffe929fe7dc54b83ac8d89087b4b0d7e0efca 100644 (file)
@@ -348,6 +348,7 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
 #define ql_dbg_tgt     0x00004000 /* Target mode */
 #define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
 #define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */
+#define ql_dbg_tgt_dif  0x00000800 /* Target mode dif */
 
 extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
        uint32_t, void **);
index 625d438e3cce01e39a57bfdd3d581ac24e6a5c55..ae119018dfaae9fe65c5cfe1869cdc655b27a3ea 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/firmware.h>
 #include <linux/aer.h>
 #include <linux/mutex.h>
+#include <linux/btree.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -395,11 +396,15 @@ struct srb_iocb {
                        struct completion comp;
                } abt;
                struct ct_arg ctarg;
+#define MAX_IOCB_MB_REG 28
+#define SIZEOF_IOCB_MB_REG (MAX_IOCB_MB_REG * sizeof(uint16_t))
                struct {
-                       __le16 in_mb[28];       /* fr fw */
-                       __le16 out_mb[28];      /* to fw */
+                       __le16 in_mb[MAX_IOCB_MB_REG];  /* from FW */
+                       __le16 out_mb[MAX_IOCB_MB_REG]; /* to FW */
                        void *out, *in;
                        dma_addr_t out_dma, in_dma;
+                       struct completion comp;
+                       int rc;
                } mbx;
                struct {
                        struct imm_ntfy_from_isp *ntfy;
@@ -437,7 +442,7 @@ typedef struct srb {
        uint32_t handle;
        uint16_t flags;
        uint16_t type;
-       char *name;
+       const char *name;
        int iocbs;
        struct qla_qpair *qpair;
        u32 gen1;       /* scratch */
@@ -2300,6 +2305,8 @@ typedef struct fc_port {
        struct ct_sns_desc ct_desc;
        enum discovery_state disc_state;
        enum login_state fw_login_state;
+       unsigned long plogi_nack_done_deadline;
+
        u32 login_gen, last_login_gen;
        u32 rscn_gen, last_rscn_gen;
        u32 chip_reset;
@@ -3106,6 +3113,16 @@ struct qla_chip_state_84xx {
        uint32_t gold_fw_version;
 };
 
+struct qla_dif_statistics {
+       uint64_t dif_input_bytes;
+       uint64_t dif_output_bytes;
+       uint64_t dif_input_requests;
+       uint64_t dif_output_requests;
+       uint32_t dif_guard_err;
+       uint32_t dif_ref_tag_err;
+       uint32_t dif_app_tag_err;
+};
+
 struct qla_statistics {
        uint32_t total_isp_aborts;
        uint64_t input_bytes;
@@ -3118,6 +3135,8 @@ struct qla_statistics {
        uint32_t stat_max_pend_cmds;
        uint32_t stat_max_qfull_cmds_alloc;
        uint32_t stat_max_qfull_cmds_dropped;
+
+       struct qla_dif_statistics qla_dif_stats;
 };
 
 struct bidi_statistics {
@@ -3125,6 +3144,16 @@ struct bidi_statistics {
        unsigned long long transfer_bytes;
 };
 
+struct qla_tc_param {
+       struct scsi_qla_host *vha;
+       uint32_t blk_sz;
+       uint32_t bufflen;
+       struct scatterlist *sg;
+       struct scatterlist *prot_sg;
+       struct crc_context *ctx;
+       uint8_t *ctx_dsd_alloced;
+};
+
 /* Multi queue support */
 #define MBC_INITIALIZE_MULTIQ 0x1f
 #define QLA_QUE_PAGE 0X1000
@@ -3272,6 +3301,8 @@ struct qlt_hw_data {
        uint8_t tgt_node_name[WWN_SIZE];
 
        struct dentry *dfs_tgt_sess;
+       struct dentry *dfs_tgt_port_database;
+
        struct list_head q_full_list;
        uint32_t num_pend_cmds;
        uint32_t num_qfull_cmds_alloc;
@@ -3281,6 +3312,7 @@ struct qlt_hw_data {
        spinlock_t sess_lock;
        int rspq_vector_cpuid;
        spinlock_t atio_lock ____cacheline_aligned;
+       struct btree_head32 host_map;
 };
 
 #define MAX_QFULL_CMDS_ALLOC   8192
@@ -3290,6 +3322,10 @@ struct qlt_hw_data {
 
 #define LEAK_EXCHG_THRESH_HOLD_PERCENT 75      /* 75 percent */
 
+#define QLA_EARLY_LINKUP(_ha) \
+       ((_ha->flags.n2n_ae || _ha->flags.lip_ae) && \
+        _ha->flags.fw_started && !_ha->flags.fw_init_done)
+
 /*
  * Qlogic host adapter specific data structure.
 */
@@ -3339,7 +3375,11 @@ struct qla_hw_data {
                uint32_t        fawwpn_enabled:1;
                uint32_t        exlogins_enabled:1;
                uint32_t        exchoffld_enabled:1;
-               /* 35 bits */
+
+               uint32_t        lip_ae:1;
+               uint32_t        n2n_ae:1;
+               uint32_t        fw_started:1;
+               uint32_t        fw_init_done:1;
        } flags;
 
        /* This spinlock is used to protect "io transactions", you must
@@ -3432,7 +3472,6 @@ struct qla_hw_data {
 #define P2P_LOOP  3
        uint8_t         interrupts_on;
        uint32_t        isp_abort_cnt;
-
 #define PCI_DEVICE_ID_QLOGIC_ISP2532    0x2532
 #define PCI_DEVICE_ID_QLOGIC_ISP8432    0x8432
 #define PCI_DEVICE_ID_QLOGIC_ISP8001   0x8001
@@ -3913,6 +3952,7 @@ typedef struct scsi_qla_host {
        struct list_head vp_fcports;    /* list of fcports */
        struct list_head work_list;
        spinlock_t work_lock;
+       struct work_struct iocb_work;
 
        /* Commonly used flags and state information. */
        struct Scsi_Host *host;
@@ -4076,6 +4116,7 @@ typedef struct scsi_qla_host {
        /* Count of active session/fcport */
        int fcport_count;
        wait_queue_head_t fcport_waitQ;
+       wait_queue_head_t vref_waitq;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
@@ -4131,14 +4172,17 @@ struct qla2_sgx {
        mb();                                           \
        if (__vha->flags.delete_progress) {             \
                atomic_dec(&__vha->vref_count);         \
+               wake_up(&__vha->vref_waitq);            \
                __bail = 1;                             \
        } else {                                        \
                __bail = 0;                             \
        }                                               \
 } while (0)
 
-#define QLA_VHA_MARK_NOT_BUSY(__vha)                   \
+#define QLA_VHA_MARK_NOT_BUSY(__vha) do {              \
        atomic_dec(&__vha->vref_count);                 \
+       wake_up(&__vha->vref_waitq);                    \
+} while (0)                                            \
 
 #define QLA_QPAIR_MARK_BUSY(__qpair, __bail) do {      \
        atomic_inc(&__qpair->ref_count);                \
index b48cce696bac77e44f7c7579fd1829a40391da2d..989e17b0758cd51ec029204c48eddf37c55c180a 100644 (file)
@@ -19,11 +19,11 @@ qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused)
        struct qla_hw_data *ha = vha->hw;
        unsigned long flags;
        struct fc_port *sess = NULL;
-       struct qla_tgt *tgt= vha->vha_tgt.qla_tgt;
+       struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
 
-       seq_printf(s, "%s\n",vha->host_str);
+       seq_printf(s, "%s\n", vha->host_str);
        if (tgt) {
-               seq_printf(s, "Port ID   Port Name                Handle\n");
+               seq_puts(s, "Port ID   Port Name                Handle\n");
 
                spin_lock_irqsave(&ha->tgt.sess_lock, flags);
                list_for_each_entry(sess, &vha->vp_fcports, list)
@@ -44,7 +44,6 @@ qla2x00_dfs_tgt_sess_open(struct inode *inode, struct file *file)
        return single_open(file, qla2x00_dfs_tgt_sess_show, vha);
 }
 
-
 static const struct file_operations dfs_tgt_sess_ops = {
        .open           = qla2x00_dfs_tgt_sess_open,
        .read           = seq_read,
@@ -52,6 +51,78 @@ static const struct file_operations dfs_tgt_sess_ops = {
        .release        = single_release,
 };
 
+static int
+qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
+{
+       scsi_qla_host_t *vha = s->private;
+       struct qla_hw_data *ha = vha->hw;
+       struct gid_list_info *gid_list;
+       dma_addr_t gid_list_dma;
+       fc_port_t fc_port;
+       char *id_iter;
+       int rc, i;
+       uint16_t entries, loop_id;
+       struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+
+       seq_printf(s, "%s\n", vha->host_str);
+       if (tgt) {
+               gid_list = dma_alloc_coherent(&ha->pdev->dev,
+                   qla2x00_gid_list_size(ha),
+                   &gid_list_dma, GFP_KERNEL);
+               if (!gid_list) {
+                       ql_dbg(ql_dbg_user, vha, 0x705c,
+                           "DMA allocation failed for %u\n",
+                            qla2x00_gid_list_size(ha));
+                       return 0;
+               }
+
+               rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma,
+                   &entries);
+               if (rc != QLA_SUCCESS)
+                       goto out_free_id_list;
+
+               id_iter = (char *)gid_list;
+
+               seq_puts(s, "Port Name  Port ID         Loop ID\n");
+
+               for (i = 0; i < entries; i++) {
+                       struct gid_list_info *gid =
+                           (struct gid_list_info *)id_iter;
+                       loop_id = le16_to_cpu(gid->loop_id);
+                       memset(&fc_port, 0, sizeof(fc_port_t));
+
+                       fc_port.loop_id = loop_id;
+
+                       rc = qla24xx_gpdb_wait(vha, &fc_port, 0);
+                       seq_printf(s, "%8phC  %02x%02x%02x  %d\n",
+                               fc_port.port_name, fc_port.d_id.b.domain,
+                               fc_port.d_id.b.area, fc_port.d_id.b.al_pa,
+                               fc_port.loop_id);
+                       id_iter += ha->gid_list_info_size;
+               }
+out_free_id_list:
+               dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
+                   gid_list, gid_list_dma);
+       }
+
+       return 0;
+}
+
+static int
+qla2x00_dfs_tgt_port_database_open(struct inode *inode, struct file *file)
+{
+       scsi_qla_host_t *vha = inode->i_private;
+
+       return single_open(file, qla2x00_dfs_tgt_port_database_show, vha);
+}
+
+static const struct file_operations dfs_tgt_port_database_ops = {
+       .open           = qla2x00_dfs_tgt_port_database_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int
 qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
 {
@@ -114,6 +185,21 @@ qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
        seq_printf(s, "num Q full sent = %lld\n",
                vha->tgt_counters.num_q_full_sent);
 
+       /* DIF stats */
+       seq_printf(s, "DIF Inp Bytes = %lld\n",
+               vha->qla_stats.qla_dif_stats.dif_input_bytes);
+       seq_printf(s, "DIF Outp Bytes = %lld\n",
+               vha->qla_stats.qla_dif_stats.dif_output_bytes);
+       seq_printf(s, "DIF Inp Req = %lld\n",
+               vha->qla_stats.qla_dif_stats.dif_input_requests);
+       seq_printf(s, "DIF Outp Req = %lld\n",
+               vha->qla_stats.qla_dif_stats.dif_output_requests);
+       seq_printf(s, "DIF Guard err = %d\n",
+               vha->qla_stats.qla_dif_stats.dif_guard_err);
+       seq_printf(s, "DIF Ref tag err = %d\n",
+               vha->qla_stats.qla_dif_stats.dif_ref_tag_err);
+       seq_printf(s, "DIF App tag err = %d\n",
+               vha->qla_stats.qla_dif_stats.dif_app_tag_err);
        return 0;
 }
 
@@ -281,6 +367,14 @@ create_nodes:
                goto out;
        }
 
+       ha->tgt.dfs_tgt_port_database = debugfs_create_file("tgt_port_database",
+           S_IRUSR,  ha->dfs_dir, vha, &dfs_tgt_port_database_ops);
+       if (!ha->tgt.dfs_tgt_port_database) {
+               ql_log(ql_log_warn, vha, 0xffff,
+                   "Unable to create debugFS tgt_port_database node.\n");
+               goto out;
+       }
+
        ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
            &dfs_fce_ops);
        if (!ha->dfs_fce) {
@@ -311,6 +405,11 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha)
                ha->tgt.dfs_tgt_sess = NULL;
        }
 
+       if (ha->tgt.dfs_tgt_port_database) {
+               debugfs_remove(ha->tgt.dfs_tgt_port_database);
+               ha->tgt.dfs_tgt_port_database = NULL;
+       }
+
        if (ha->dfs_fw_resource_cnt) {
                debugfs_remove(ha->dfs_fw_resource_cnt);
                ha->dfs_fw_resource_cnt = NULL;
index b3d6441d1d90eb27f1908fa27ea1ec28f024b1d9..5b2451745e9f471988e8685d68f3423ec5d5811f 100644 (file)
@@ -193,6 +193,7 @@ extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *);
 void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
        uint16_t *);
 int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
+int qla24xx_async_abort_cmd(srb_t *);
 
 /*
  * Global Functions in qla_mid.c source file.
@@ -256,11 +257,11 @@ extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
 extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
 extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
 extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
-       uint32_t *, uint16_t, struct qla_tgt_cmd *);
+       uint32_t *, uint16_t, struct qla_tc_param *);
 extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
-       uint32_t *, uint16_t, struct qla_tgt_cmd *);
+       uint32_t *, uint16_t, struct qla_tc_param *);
 extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
-       uint32_t *, uint16_t, struct qla_tgt_cmd *);
+       uint32_t *, uint16_t, struct qla_tc_param *);
 extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
 extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
 extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
@@ -368,7 +369,7 @@ qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
 
 extern int
 qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
-    dma_addr_t, uint);
+    dma_addr_t, uint16_t);
 
 extern int qla24xx_abort_command(srb_t *);
 extern int qla24xx_async_abort_command(srb_t *);
@@ -472,6 +473,13 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
 extern int
 qla26xx_dport_diagnostics(scsi_qla_host_t *, void *, uint, uint);
 
+int qla24xx_send_mb_cmd(struct scsi_qla_host *, mbx_cmd_t *);
+int qla24xx_gpdb_wait(struct scsi_qla_host *, fc_port_t *, u8);
+int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
+    uint16_t *);
+int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *,
+       struct port_database_24xx *);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
@@ -846,5 +854,7 @@ extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
        uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
 void qla24xx_delete_sess_fn(struct work_struct *);
 void qlt_unknown_atio_work_fn(struct work_struct *);
+void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
+void qlt_remove_target_resources(struct qla_hw_data *);
 
 #endif /* _QLA_GBL_H */
index 32fb9007f13770e4cd43650521b67e991a66d3e9..f9d2fe7b1adedf9349c11b7bfaf389c223a21ba8 100644 (file)
@@ -629,7 +629,6 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
        struct srb *sp = s;
        struct scsi_qla_host *vha = sp->vha;
        struct qla_hw_data *ha = vha->hw;
-       uint64_t zero = 0;
        struct port_database_24xx *pd;
        fc_port_t *fcport = sp->fcport;
        u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
@@ -649,48 +648,7 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 
        pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
 
-       /* Check for logged in state. */
-       if (pd->current_login_state != PDS_PRLI_COMPLETE &&
-           pd->last_login_state != PDS_PRLI_COMPLETE) {
-               ql_dbg(ql_dbg_mbx, vha, 0xffff,
-                   "Unable to verify login-state (%x/%x) for "
-                   "loop_id %x.\n", pd->current_login_state,
-                   pd->last_login_state, fcport->loop_id);
-               rval = QLA_FUNCTION_FAILED;
-               goto gpd_error_out;
-       }
-
-       if (fcport->loop_id == FC_NO_LOOP_ID ||
-           (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
-               memcmp(fcport->port_name, pd->port_name, 8))) {
-               /* We lost the device mid way. */
-               rval = QLA_NOT_LOGGED_IN;
-               goto gpd_error_out;
-       }
-
-       /* Names are little-endian. */
-       memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
-
-       /* Get port_id of device. */
-       fcport->d_id.b.domain = pd->port_id[0];
-       fcport->d_id.b.area = pd->port_id[1];
-       fcport->d_id.b.al_pa = pd->port_id[2];
-       fcport->d_id.b.rsvd_1 = 0;
-
-       /* If not target must be initiator or unknown type. */
-       if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
-               fcport->port_type = FCT_INITIATOR;
-       else
-               fcport->port_type = FCT_TARGET;
-
-       /* Passback COS information. */
-       fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
-               FC_COS_CLASS2 : FC_COS_CLASS3;
-
-       if (pd->prli_svc_param_word_3[0] & BIT_7) {
-               fcport->flags |= FCF_CONF_COMP_SUPPORTED;
-               fcport->conf_compl_supported = 1;
-       }
+       rval = __qla24xx_parse_gpdb(vha, fcport, pd);
 
 gpd_error_out:
        memset(&ea, 0, sizeof(ea));
@@ -876,10 +834,14 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
        fcport->login_retry--;
 
        if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
-           (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
            (fcport->fw_login_state == DSC_LS_PRLI_PEND))
                return 0;
 
+       if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
+               if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline))
+                       return 0;
+       }
+
        /* for pure Target Mode. Login will not be initiated */
        if (vha->host->active_mode == MODE_TARGET)
                return 0;
@@ -1041,10 +1003,14 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
                fcport->flags);
 
        if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
-           (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
            (fcport->fw_login_state == DSC_LS_PRLI_PEND))
                return;
 
+       if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
+               if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline))
+                       return;
+       }
+
        if (fcport->flags & FCF_ASYNC_SENT) {
                fcport->login_retry++;
                set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
@@ -1258,7 +1224,7 @@ qla24xx_abort_sp_done(void *ptr, int res)
        complete(&abt->u.abt.comp);
 }
 
-static int
+int
 qla24xx_async_abort_cmd(srb_t *cmd_sp)
 {
        scsi_qla_host_t *vha = cmd_sp->vha;
@@ -3212,6 +3178,7 @@ next_check:
        } else {
                ql_dbg(ql_dbg_init, vha, 0x00d3,
                    "Init Firmware -- success.\n");
+               ha->flags.fw_started = 1;
        }
 
        return (rval);
@@ -3374,8 +3341,8 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
        uint8_t       domain;
        char            connect_type[22];
        struct qla_hw_data *ha = vha->hw;
-       unsigned long flags;
        scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+       port_id_t id;
 
        /* Get host addresses. */
        rval = qla2x00_get_adapter_id(vha,
@@ -3453,13 +3420,11 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
 
        /* Save Host port and loop ID. */
        /* byte order - Big Endian */
-       vha->d_id.b.domain = domain;
-       vha->d_id.b.area = area;
-       vha->d_id.b.al_pa = al_pa;
-
-       spin_lock_irqsave(&ha->vport_slock, flags);
-       qlt_update_vp_map(vha, SET_AL_PA);
-       spin_unlock_irqrestore(&ha->vport_slock, flags);
+       id.b.domain = domain;
+       id.b.area = area;
+       id.b.al_pa = al_pa;
+       id.b.rsvd_1 = 0;
+       qlt_update_host_map(vha, id);
 
        if (!vha->flags.init_done)
                ql_log(ql_log_info, vha, 0x2010,
@@ -4036,6 +4001,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
                        atomic_set(&vha->loop_state, LOOP_READY);
                        ql_dbg(ql_dbg_disc, vha, 0x2069,
                            "LOOP READY.\n");
+                       ha->flags.fw_init_done = 1;
 
                        /*
                         * Process any ATIO queue entries that came in
@@ -5148,6 +5114,7 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
                        }
                }
                atomic_dec(&vha->vref_count);
+               wake_up(&vha->vref_waitq);
        }
        spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
@@ -5526,6 +5493,11 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        if (!(IS_P3P_TYPE(ha)))
                ha->isp_ops->reset_chip(vha);
 
+       ha->flags.n2n_ae = 0;
+       ha->flags.lip_ae = 0;
+       ha->current_topology = 0;
+       ha->flags.fw_started = 0;
+       ha->flags.fw_init_done = 0;
        ha->chip_reset++;
 
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@ -6802,6 +6774,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
                return;
        if (!ha->fw_major_version)
                return;
+       if (!ha->flags.fw_started)
+               return;
 
        ret = qla2x00_stop_firmware(vha);
        for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
@@ -6815,6 +6789,9 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
                    "Attempting retry of stop-firmware command.\n");
                ret = qla2x00_stop_firmware(vha);
        }
+
+       ha->flags.fw_started = 0;
+       ha->flags.fw_init_done = 0;
 }
 
 int
index 535079280288fbd6554a3ca28e620065b8b9fe98..ea027f6a7fd4e949c1a9a53aad0de00b0a7ee361 100644 (file)
@@ -889,7 +889,7 @@ qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx,
 
 int
 qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
-       uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
+       uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
 {
        void *next_dsd;
        uint8_t avail_dsds = 0;
@@ -898,7 +898,6 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
        struct scatterlist *sg_prot;
        uint32_t *cur_dsd = dsd;
        uint16_t        used_dsds = tot_dsds;
-
        uint32_t        prot_int; /* protection interval */
        uint32_t        partial;
        struct qla2_sgx sgx;
@@ -966,7 +965,7 @@ alloc_and_fill:
                        } else {
                                list_add_tail(&dsd_ptr->list,
                                    &(tc->ctx->dsd_list));
-                               tc->ctx_dsd_alloced = 1;
+                               *tc->ctx_dsd_alloced = 1;
                        }
 
 
@@ -1005,7 +1004,7 @@ alloc_and_fill:
 
 int
 qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
-       uint16_t tot_dsds, struct qla_tgt_cmd *tc)
+       uint16_t tot_dsds, struct qla_tc_param *tc)
 {
        void *next_dsd;
        uint8_t avail_dsds = 0;
@@ -1066,7 +1065,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
                        } else {
                                list_add_tail(&dsd_ptr->list,
                                    &(tc->ctx->dsd_list));
-                               tc->ctx_dsd_alloced = 1;
+                               *tc->ctx_dsd_alloced = 1;
                        }
 
                        /* add new list to cmd iocb or last list */
@@ -1092,7 +1091,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
 
 int
 qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
-       uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
+       uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
 {
        void *next_dsd;
        uint8_t avail_dsds = 0;
@@ -1158,7 +1157,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
                        } else {
                                list_add_tail(&dsd_ptr->list,
                                    &(tc->ctx->dsd_list));
-                               tc->ctx_dsd_alloced = 1;
+                               *tc->ctx_dsd_alloced = 1;
                        }
 
                        /* add new list to cmd iocb or last list */
index 3c66ea29de2704fcefc71e965c071aa05c7bca78..3203367a4f423608ab69d75882d5a3141a1465a1 100644 (file)
@@ -708,6 +708,8 @@ skip_rio:
                    "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
 
                ha->isp_ops->fw_dump(vha, 1);
+               ha->flags.fw_init_done = 0;
+               ha->flags.fw_started = 0;
 
                if (IS_FWI2_CAPABLE(ha)) {
                        if (mb[1] == 0 && mb[2] == 0) {
@@ -761,6 +763,9 @@ skip_rio:
                break;
 
        case MBA_LIP_OCCURRED:          /* Loop Initialization Procedure */
+               ha->flags.lip_ae = 1;
+               ha->flags.n2n_ae = 0;
+
                ql_dbg(ql_dbg_async, vha, 0x5009,
                    "LIP occurred (%x).\n", mb[1]);
 
@@ -797,6 +802,10 @@ skip_rio:
                break;
 
        case MBA_LOOP_DOWN:             /* Loop Down Event */
+               ha->flags.n2n_ae = 0;
+               ha->flags.lip_ae = 0;
+               ha->current_topology = 0;
+
                mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
                        ? RD_REG_WORD(&reg24->mailbox4) : 0;
                mbx = (IS_P3P_TYPE(ha)) ? RD_REG_WORD(&reg82->mailbox_out[4])
@@ -866,6 +875,9 @@ skip_rio:
 
        /* case MBA_DCBX_COMPLETE: */
        case MBA_POINT_TO_POINT:        /* Point-to-Point */
+               ha->flags.lip_ae = 0;
+               ha->flags.n2n_ae = 1;
+
                if (IS_QLA2100(ha))
                        break;
 
@@ -1620,9 +1632,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
                QLA_LOGIO_LOGIN_RETRIED : 0;
        if (logio->entry_status) {
                ql_log(ql_log_warn, fcport->vha, 0x5034,
-                   "Async-%s error entry - hdl=%x"
+                   "Async-%s error entry - %8phC hdl=%x"
                    "portid=%02x%02x%02x entry-status=%x.\n",
-                   type, sp->handle, fcport->d_id.b.domain,
+                   type, fcport->port_name, sp->handle, fcport->d_id.b.domain,
                    fcport->d_id.b.area, fcport->d_id.b.al_pa,
                    logio->entry_status);
                ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d,
@@ -1633,8 +1645,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 
        if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
                ql_dbg(ql_dbg_async, fcport->vha, 0x5036,
-                   "Async-%s complete - hdl=%x portid=%02x%02x%02x "
-                   "iop0=%x.\n", type, sp->handle, fcport->d_id.b.domain,
+                   "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x "
+                   "iop0=%x.\n", type, fcport->port_name, sp->handle,
+                   fcport->d_id.b.domain,
                    fcport->d_id.b.area, fcport->d_id.b.al_pa,
                    le32_to_cpu(logio->io_parameter[0]));
 
@@ -1674,6 +1687,17 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
        case LSC_SCODE_NPORT_USED:
                data[0] = MBS_LOOP_ID_USED;
                break;
+       case LSC_SCODE_CMD_FAILED:
+               if (iop[1] == 0x0606) {
+                       /*
+                        * PLOGI/PRLI Completed. We must have Recv PLOGI/PRLI,
+                        * Target side acked.
+                        */
+                       data[0] = MBS_COMMAND_COMPLETE;
+                       goto logio_done;
+               }
+               data[0] = MBS_COMMAND_ERROR;
+               break;
        case LSC_SCODE_NOXCB:
                vha->hw->exch_starvation++;
                if (vha->hw->exch_starvation > 5) {
@@ -1695,8 +1719,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
        }
 
        ql_dbg(ql_dbg_async, fcport->vha, 0x5037,
-           "Async-%s failed - hdl=%x portid=%02x%02x%02x comp=%x "
-           "iop0=%x iop1=%x.\n", type, sp->handle, fcport->d_id.b.domain,
+           "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x "
+           "iop0=%x iop1=%x.\n", type, fcport->port_name,
+               sp->handle, fcport->d_id.b.domain,
            fcport->d_id.b.area, fcport->d_id.b.al_pa,
            le16_to_cpu(logio->comp_status),
            le32_to_cpu(logio->io_parameter[0]),
@@ -2679,7 +2704,7 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
                return;
 
        abt = &sp->u.iocb_cmd;
-       abt->u.abt.comp_status = le32_to_cpu(pkt->nport_handle);
+       abt->u.abt.comp_status = le16_to_cpu(pkt->nport_handle);
        sp->done(sp, 0);
 }
 
@@ -2693,7 +2718,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
        struct sts_entry_24xx *pkt;
        struct qla_hw_data *ha = vha->hw;
 
-       if (!vha->flags.online)
+       if (!ha->flags.fw_started)
                return;
 
        while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
index 35079f4174179967d99568a4491713d82d96c7a3..a113ab3592a7f86eb16ce8f76d82337557cab029 100644 (file)
 #include <linux/delay.h>
 #include <linux/gfp.h>
 
+static struct mb_cmd_name {
+       uint16_t cmd;
+       const char *str;
+} mb_str[] = {
+       {MBC_GET_PORT_DATABASE,         "GPDB"},
+       {MBC_GET_ID_LIST,               "GIDList"},
+       {MBC_GET_LINK_PRIV_STATS,       "Stats"},
+};
+
+static const char *mb_to_str(uint16_t cmd)
+{
+       int i;
+       struct mb_cmd_name *e;
+
+       for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
+               e = mb_str + i;
+               if (cmd == e->cmd)
+                       return e->str;
+       }
+       return "unknown";
+}
+
 static struct rom_cmd {
        uint16_t cmd;
 } rom_cmds[] = {
@@ -2818,7 +2840,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
 
 int
 qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
-    dma_addr_t stats_dma, uint options)
+    dma_addr_t stats_dma, uint16_t options)
 {
        int rval;
        mbx_cmd_t mc;
@@ -2828,19 +2850,17 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088,
            "Entered %s.\n", __func__);
 
-       mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
-       mcp->mb[2] = MSW(stats_dma);
-       mcp->mb[3] = LSW(stats_dma);
-       mcp->mb[6] = MSW(MSD(stats_dma));
-       mcp->mb[7] = LSW(MSD(stats_dma));
-       mcp->mb[8] = sizeof(struct link_statistics) / 4;
-       mcp->mb[9] = vha->vp_idx;
-       mcp->mb[10] = options;
-       mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
-       mcp->in_mb = MBX_2|MBX_1|MBX_0;
-       mcp->tov = MBX_TOV_SECONDS;
-       mcp->flags = IOCTL_CMD;
-       rval = qla2x00_mailbox_command(vha, mcp);
+       memset(&mc, 0, sizeof(mc));
+       mc.mb[0] = MBC_GET_LINK_PRIV_STATS;
+       mc.mb[2] = MSW(stats_dma);
+       mc.mb[3] = LSW(stats_dma);
+       mc.mb[6] = MSW(MSD(stats_dma));
+       mc.mb[7] = LSW(MSD(stats_dma));
+       mc.mb[8] = sizeof(struct link_statistics) / 4;
+       mc.mb[9] = cpu_to_le16(vha->vp_idx);
+       mc.mb[10] = cpu_to_le16(options);
+
+       rval = qla24xx_send_mb_cmd(vha, &mc);
 
        if (rval == QLA_SUCCESS) {
                if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
@@ -3603,6 +3623,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
        scsi_qla_host_t *vp = NULL;
        unsigned long   flags;
        int found;
+       port_id_t id;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6,
            "Entered %s.\n", __func__);
@@ -3610,28 +3631,27 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
        if (rptid_entry->entry_status != 0)
                return;
 
+       id.b.domain = rptid_entry->port_id[2];
+       id.b.area   = rptid_entry->port_id[1];
+       id.b.al_pa  = rptid_entry->port_id[0];
+       id.b.rsvd_1 = 0;
+
        if (rptid_entry->format == 0) {
                /* loop */
-               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
+               ql_dbg(ql_dbg_async, vha, 0x10b7,
                    "Format 0 : Number of VPs setup %d, number of "
                    "VPs acquired %d.\n", rptid_entry->vp_setup,
                    rptid_entry->vp_acquired);
-               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8,
+               ql_dbg(ql_dbg_async, vha, 0x10b8,
                    "Primary port id %02x%02x%02x.\n",
                    rptid_entry->port_id[2], rptid_entry->port_id[1],
                    rptid_entry->port_id[0]);
 
-               vha->d_id.b.domain = rptid_entry->port_id[2];
-               vha->d_id.b.area = rptid_entry->port_id[1];
-               vha->d_id.b.al_pa = rptid_entry->port_id[0];
-
-               spin_lock_irqsave(&ha->vport_slock, flags);
-               qlt_update_vp_map(vha, SET_AL_PA);
-               spin_unlock_irqrestore(&ha->vport_slock, flags);
+               qlt_update_host_map(vha, id);
 
        } else if (rptid_entry->format == 1) {
                /* fabric */
-               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9,
+               ql_dbg(ql_dbg_async, vha, 0x10b9,
                    "Format 1: VP[%d] enabled - status %d - with "
                    "port id %02x%02x%02x.\n", rptid_entry->vp_idx,
                        rptid_entry->vp_status,
@@ -3653,12 +3673,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                                            WWN_SIZE);
                                }
 
-                               vha->d_id.b.domain = rptid_entry->port_id[2];
-                               vha->d_id.b.area = rptid_entry->port_id[1];
-                               vha->d_id.b.al_pa = rptid_entry->port_id[0];
-                               spin_lock_irqsave(&ha->vport_slock, flags);
-                               qlt_update_vp_map(vha, SET_AL_PA);
-                               spin_unlock_irqrestore(&ha->vport_slock, flags);
+                               qlt_update_host_map(vha, id);
                        }
 
                        fc_host_port_name(vha->host) =
@@ -3694,12 +3709,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                        if (!found)
                                return;
 
-                       vp->d_id.b.domain = rptid_entry->port_id[2];
-                       vp->d_id.b.area =  rptid_entry->port_id[1];
-                       vp->d_id.b.al_pa = rptid_entry->port_id[0];
-                       spin_lock_irqsave(&ha->vport_slock, flags);
-                       qlt_update_vp_map(vp, SET_AL_PA);
-                       spin_unlock_irqrestore(&ha->vport_slock, flags);
+                       qlt_update_host_map(vp, id);
 
                        /*
                         * Cannot configure here as we are still sitting on the
@@ -5827,3 +5837,225 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
 
        return rval;
 }
+
+static void qla2x00_async_mb_sp_done(void *s, int res)
+{
+       struct srb *sp = s;
+
+       sp->u.iocb_cmd.u.mbx.rc = res;
+
+       complete(&sp->u.iocb_cmd.u.mbx.comp);
+       /* don't free sp here. Let the caller do the free */
+}
+
+/*
+ * This mailbox uses the iocb interface to send MB command.
+ * This allows non-critial (non chip setup) command to go
+ * out in parrallel.
+ */
+int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
+{
+       int rval = QLA_FUNCTION_FAILED;
+       srb_t *sp;
+       struct srb_iocb *c;
+
+       if (!vha->hw->flags.fw_started)
+               goto done;
+
+       sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+       if (!sp)
+               goto done;
+
+       sp->type = SRB_MB_IOCB;
+       sp->name = mb_to_str(mcp->mb[0]);
+
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+       memcpy(sp->u.iocb_cmd.u.mbx.out_mb, mcp->mb, SIZEOF_IOCB_MB_REG);
+
+       c = &sp->u.iocb_cmd;
+       c->timeout = qla2x00_async_iocb_timeout;
+       init_completion(&c->u.mbx.comp);
+
+       sp->done = qla2x00_async_mb_sp_done;
+
+       rval = qla2x00_start_sp(sp);
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0xffff,
+                   "%s: %s Failed submission. %x.\n",
+                   __func__, sp->name, rval);
+               goto done_free_sp;
+       }
+
+       ql_dbg(ql_dbg_mbx, vha, 0xffff, "MB:%s hndl %x submitted\n",
+           sp->name, sp->handle);
+
+       wait_for_completion(&c->u.mbx.comp);
+       memcpy(mcp->mb, sp->u.iocb_cmd.u.mbx.in_mb, SIZEOF_IOCB_MB_REG);
+
+       rval = c->u.mbx.rc;
+       switch (rval) {
+       case QLA_FUNCTION_TIMEOUT:
+               ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %s Timeout. %x.\n",
+                   __func__, sp->name, rval);
+               break;
+       case  QLA_SUCCESS:
+               ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %s done.\n",
+                   __func__, sp->name);
+               sp->free(sp);
+               break;
+       default:
+               ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %s Failed. %x.\n",
+                   __func__, sp->name, rval);
+               sp->free(sp);
+               break;
+       }
+
+       return rval;
+
+done_free_sp:
+       sp->free(sp);
+done:
+       return rval;
+}
+
+/*
+ * qla24xx_gpdb_wait
+ * NOTE: Do not call this routine from DPC thread
+ */
+int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+{
+       int rval = QLA_FUNCTION_FAILED;
+       dma_addr_t pd_dma;
+       struct port_database_24xx *pd;
+       struct qla_hw_data *ha = vha->hw;
+       mbx_cmd_t mc;
+
+       if (!vha->hw->flags.fw_started)
+               goto done;
+
+       pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
+       if (pd  == NULL) {
+               ql_log(ql_log_warn, vha, 0xffff,
+                       "Failed to allocate port database structure.\n");
+               goto done_free_sp;
+       }
+       memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
+
+       memset(&mc, 0, sizeof(mc));
+       mc.mb[0] = MBC_GET_PORT_DATABASE;
+       mc.mb[1] = cpu_to_le16(fcport->loop_id);
+       mc.mb[2] = MSW(pd_dma);
+       mc.mb[3] = LSW(pd_dma);
+       mc.mb[6] = MSW(MSD(pd_dma));
+       mc.mb[7] = LSW(MSD(pd_dma));
+       mc.mb[9] = cpu_to_le16(vha->vp_idx);
+       mc.mb[10] = cpu_to_le16((uint16_t)opt);
+
+       rval = qla24xx_send_mb_cmd(vha, &mc);
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0xffff,
+                   "%s: %8phC fail\n", __func__, fcport->port_name);
+               goto done_free_sp;
+       }
+
+       rval = __qla24xx_parse_gpdb(vha, fcport, pd);
+
+       ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %8phC done\n",
+           __func__, fcport->port_name);
+
+done_free_sp:
+       if (pd)
+               dma_pool_free(ha->s_dma_pool, pd, pd_dma);
+done:
+       return rval;
+}
+
+int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
+    struct port_database_24xx *pd)
+{
+       int rval = QLA_SUCCESS;
+       uint64_t zero = 0;
+
+       /* Check for logged in state. */
+       if (pd->current_login_state != PDS_PRLI_COMPLETE &&
+               pd->last_login_state != PDS_PRLI_COMPLETE) {
+               ql_dbg(ql_dbg_mbx, vha, 0xffff,
+                          "Unable to verify login-state (%x/%x) for "
+                          "loop_id %x.\n", pd->current_login_state,
+                          pd->last_login_state, fcport->loop_id);
+               rval = QLA_FUNCTION_FAILED;
+               goto gpd_error_out;
+       }
+
+       if (fcport->loop_id == FC_NO_LOOP_ID ||
+           (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
+            memcmp(fcport->port_name, pd->port_name, 8))) {
+               /* We lost the device mid way. */
+               rval = QLA_NOT_LOGGED_IN;
+               goto gpd_error_out;
+       }
+
+       /* Names are little-endian. */
+       memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
+       memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
+
+       /* Get port_id of device. */
+       fcport->d_id.b.domain = pd->port_id[0];
+       fcport->d_id.b.area = pd->port_id[1];
+       fcport->d_id.b.al_pa = pd->port_id[2];
+       fcport->d_id.b.rsvd_1 = 0;
+
+       /* If not target must be initiator or unknown type. */
+       if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
+               fcport->port_type = FCT_INITIATOR;
+       else
+               fcport->port_type = FCT_TARGET;
+
+       /* Passback COS information. */
+       fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
+               FC_COS_CLASS2 : FC_COS_CLASS3;
+
+       if (pd->prli_svc_param_word_3[0] & BIT_7) {
+               fcport->flags |= FCF_CONF_COMP_SUPPORTED;
+               fcport->conf_compl_supported = 1;
+       }
+
+gpd_error_out:
+       return rval;
+}
+
+/*
+ * qla24xx_gidlist__wait
+ * NOTE: don't call this routine from DPC thread.
+ */
+int qla24xx_gidlist_wait(struct scsi_qla_host *vha,
+       void *id_list, dma_addr_t id_list_dma, uint16_t *entries)
+{
+       int rval = QLA_FUNCTION_FAILED;
+       mbx_cmd_t mc;
+
+       if (!vha->hw->flags.fw_started)
+               goto done;
+
+       memset(&mc, 0, sizeof(mc));
+       mc.mb[0] = MBC_GET_ID_LIST;
+       mc.mb[2] = MSW(id_list_dma);
+       mc.mb[3] = LSW(id_list_dma);
+       mc.mb[6] = MSW(MSD(id_list_dma));
+       mc.mb[7] = LSW(MSD(id_list_dma));
+       mc.mb[8] = 0;
+       mc.mb[9] = cpu_to_le16(vha->vp_idx);
+
+       rval = qla24xx_send_mb_cmd(vha, &mc);
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0xffff,
+                       "%s:  fail\n", __func__);
+       } else {
+               *entries = mc.mb[1];
+               ql_dbg(ql_dbg_mbx, vha, 0xffff,
+                       "%s:  done\n", __func__);
+       }
+done:
+       return rval;
+}
index c6d6f0d912ff75ffaf9b9d810f81af735e39549b..09a490c98763a9406a6eafd3082df8f8ed50a149 100644 (file)
@@ -74,13 +74,14 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
         * ensures no active vp_list traversal while the vport is removed
         * from the queue)
         */
-       spin_lock_irqsave(&ha->vport_slock, flags);
-       while (atomic_read(&vha->vref_count)) {
-               spin_unlock_irqrestore(&ha->vport_slock, flags);
-
-               msleep(500);
+       wait_event_timeout(vha->vref_waitq, atomic_read(&vha->vref_count),
+           10*HZ);
 
-               spin_lock_irqsave(&ha->vport_slock, flags);
+       spin_lock_irqsave(&ha->vport_slock, flags);
+       if (atomic_read(&vha->vref_count)) {
+               ql_dbg(ql_dbg_vport, vha, 0xfffa,
+                   "vha->vref_count=%u timeout\n", vha->vref_count.counter);
+               vha->vref_count = (atomic_t)ATOMIC_INIT(0);
        }
        list_del(&vha->list);
        qlt_update_vp_map(vha, RESET_VP_IDX);
@@ -269,6 +270,7 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
 
                        spin_lock_irqsave(&ha->vport_slock, flags);
                        atomic_dec(&vha->vref_count);
+                       wake_up(&vha->vref_waitq);
                }
                i++;
        }
index 1fed235a1b4a03172a4717a360a90f29ae383a4f..41d5b09f7326fb706f132fc64bcfe54023e37309 100644 (file)
@@ -2560,6 +2560,20 @@ qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
        return atomic_read(&vha->loop_state) == LOOP_READY;
 }
 
+static void qla2x00_iocb_work_fn(struct work_struct *work)
+{
+       struct scsi_qla_host *vha = container_of(work,
+               struct scsi_qla_host, iocb_work);
+       int cnt = 0;
+
+       while (!list_empty(&vha->work_list)) {
+               qla2x00_do_work(vha);
+               cnt++;
+               if (cnt > 10)
+                       break;
+       }
+}
+
 /*
  * PCI driver interface
  */
@@ -3078,6 +3092,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
         */
        qla2xxx_wake_dpc(base_vha);
 
+       INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
        INIT_WORK(&ha->board_disable, qla2x00_disable_board_on_pci_error);
 
        if (IS_QLA8031(ha) || IS_MCTP_CAPABLE(ha)) {
@@ -3469,6 +3484,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
        qla2x00_free_sysfs_attr(base_vha, true);
 
        fc_remove_host(base_vha->host);
+       qlt_remove_target_resources(ha);
 
        scsi_remove_host(base_vha->host);
 
@@ -4268,6 +4284,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
        spin_lock_init(&vha->work_lock);
        spin_lock_init(&vha->cmd_list_lock);
        init_waitqueue_head(&vha->fcport_waitQ);
+       init_waitqueue_head(&vha->vref_waitq);
 
        vha->gnl.size = sizeof(struct get_name_list_extended) *
                        (ha->max_loop_id + 1);
@@ -4319,7 +4336,11 @@ qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
        spin_lock_irqsave(&vha->work_lock, flags);
        list_add_tail(&e->list, &vha->work_list);
        spin_unlock_irqrestore(&vha->work_lock, flags);
-       qla2xxx_wake_dpc(vha);
+
+       if (QLA_EARLY_LINKUP(vha->hw))
+               schedule_work(&vha->iocb_work);
+       else
+               qla2xxx_wake_dpc(vha);
 
        return QLA_SUCCESS;
 }
index 45f5077684f0a5b39c0645ddee831bf4071667d4..0e03ca2ab3e52358c817cdd2cdc667ba2bfb1ba3 100644 (file)
@@ -130,6 +130,9 @@ static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
 static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha,
        fc_port_t *fcport, bool local);
 void qlt_unreg_sess(struct fc_port *sess);
+static void qlt_24xx_handle_abts(struct scsi_qla_host *,
+       struct abts_recv_from_24xx *);
+
 /*
  * Global Variables
  */
@@ -140,6 +143,20 @@ static struct workqueue_struct *qla_tgt_wq;
 static DEFINE_MUTEX(qla_tgt_mutex);
 static LIST_HEAD(qla_tgt_glist);
 
+static const char *prot_op_str(u32 prot_op)
+{
+       switch (prot_op) {
+       case TARGET_PROT_NORMAL:        return "NORMAL";
+       case TARGET_PROT_DIN_INSERT:    return "DIN_INSERT";
+       case TARGET_PROT_DOUT_INSERT:   return "DOUT_INSERT";
+       case TARGET_PROT_DIN_STRIP:     return "DIN_STRIP";
+       case TARGET_PROT_DOUT_STRIP:    return "DOUT_STRIP";
+       case TARGET_PROT_DIN_PASS:      return "DIN_PASS";
+       case TARGET_PROT_DOUT_PASS:     return "DOUT_PASS";
+       default:                        return "UNKNOWN";
+       }
+}
+
 /* This API intentionally takes dest as a parameter, rather than returning
  * int value to avoid caller forgetting to issue wmb() after the store */
 void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
@@ -170,21 +187,23 @@ static inline
 struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
        uint8_t *d_id)
 {
-       struct qla_hw_data *ha = vha->hw;
-       uint8_t vp_idx;
-
-       if ((vha->d_id.b.area != d_id[1]) || (vha->d_id.b.domain != d_id[0]))
-               return NULL;
+       struct scsi_qla_host *host;
+       uint32_t key = 0;
 
-       if (vha->d_id.b.al_pa == d_id[2])
+       if ((vha->d_id.b.area == d_id[1]) && (vha->d_id.b.domain == d_id[0]) &&
+           (vha->d_id.b.al_pa == d_id[2]))
                return vha;
 
-       BUG_ON(ha->tgt.tgt_vp_map == NULL);
-       vp_idx = ha->tgt.tgt_vp_map[d_id[2]].idx;
-       if (likely(test_bit(vp_idx, ha->vp_idx_map)))
-               return ha->tgt.tgt_vp_map[vp_idx].vha;
+       key  = (uint32_t)d_id[0] << 16;
+       key |= (uint32_t)d_id[1] <<  8;
+       key |= (uint32_t)d_id[2];
 
-       return NULL;
+       host = btree_lookup32(&vha->hw->tgt.host_map, key);
+       if (!host)
+               ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+                          "Unable to find host %06x\n", key);
+
+       return host;
 }
 
 static inline
@@ -389,6 +408,8 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
                        (struct abts_recv_from_24xx *)atio;
                struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha,
                        entry->vp_index);
+               unsigned long flags;
+
                if (unlikely(!host)) {
                        ql_dbg(ql_dbg_tgt, vha, 0xffff,
                            "qla_target(%d): Response pkt (ABTS_RECV_24XX) "
@@ -396,9 +417,12 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
                            vha->vp_idx, entry->vp_index);
                        break;
                }
-               qlt_response_pkt(host, (response_t *)atio);
+               if (!ha_locked)
+                       spin_lock_irqsave(&host->hw->hardware_lock, flags);
+               qlt_24xx_handle_abts(host, (struct abts_recv_from_24xx *)atio);
+               if (!ha_locked)
+                       spin_unlock_irqrestore(&host->hw->hardware_lock, flags);
                break;
-
        }
 
        /* case PUREX_IOCB_TYPE: ql2xmvasynctoatio */
@@ -554,6 +578,7 @@ void qla2x00_async_nack_sp_done(void *s, int res)
                sp->fcport->login_gen++;
                sp->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
                sp->fcport->logout_on_delete = 1;
+               sp->fcport->plogi_nack_done_deadline = jiffies + HZ;
                break;
 
        case SRB_NACK_PRLI:
@@ -613,6 +638,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
                break;
        case SRB_NACK_PRLI:
                fcport->fw_login_state = DSC_LS_PRLI_PEND;
+               fcport->deleted = 0;
                c = "PRLI";
                break;
        case SRB_NACK_LOGO:
@@ -1215,7 +1241,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
        }
 
        /* Get list of logged in devices */
-       rc = qla2x00_get_id_list(vha, gid_list, gid_list_dma, &entries);
+       rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma, &entries);
        if (rc != QLA_SUCCESS) {
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf045,
                    "qla_target(%d): get_id_list() failed: %x\n",
@@ -1551,6 +1577,9 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
        request_t *pkt;
        struct nack_to_isp *nack;
 
+       if (!ha->flags.fw_started)
+               return;
+
        ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha);
 
        /* Send marker if required */
@@ -2013,6 +2042,70 @@ void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
 }
 EXPORT_SYMBOL(qlt_free_mcmd);
 
+/*
+ * ha->hardware_lock supposed to be held on entry. Might drop it, then
+ * reacquire
+ */
+void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
+    uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq)
+{
+       struct atio_from_isp *atio = &cmd->atio;
+       struct ctio7_to_24xx *ctio;
+       uint16_t temp;
+
+       ql_dbg(ql_dbg_tgt_dif, vha, 0x3066,
+           "Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, "
+           "sense_key=%02x, asc=%02x, ascq=%02x",
+           vha, atio, scsi_status, sense_key, asc, ascq);
+
+       ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL);
+       if (!ctio) {
+               ql_dbg(ql_dbg_async, vha, 0x3067,
+                   "qla2x00t(%ld): %s failed: unable to allocate request packet",
+                   vha->host_no, __func__);
+               goto out;
+       }
+
+       ctio->entry_type = CTIO_TYPE7;
+       ctio->entry_count = 1;
+       ctio->handle = QLA_TGT_SKIP_HANDLE;
+       ctio->nport_handle = cmd->sess->loop_id;
+       ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
+       ctio->vp_index = vha->vp_idx;
+       ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
+       ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
+       ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+       ctio->exchange_addr = atio->u.isp24.exchange_addr;
+       ctio->u.status1.flags = (atio->u.isp24.attr << 9) |
+           cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
+       temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
+       ctio->u.status1.ox_id = cpu_to_le16(temp);
+       ctio->u.status1.scsi_status =
+           cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID | scsi_status);
+       ctio->u.status1.response_len = cpu_to_le16(18);
+       ctio->u.status1.residual = cpu_to_le32(get_datalen_for_atio(atio));
+
+       if (ctio->u.status1.residual != 0)
+               ctio->u.status1.scsi_status |=
+                   cpu_to_le16(SS_RESIDUAL_UNDER);
+
+       /* Response code and sense key */
+       put_unaligned_le32(((0x70 << 24) | (sense_key << 8)),
+           (&ctio->u.status1.sense_data)[0]);
+       /* Additional sense length */
+       put_unaligned_le32(0x0a, (&ctio->u.status1.sense_data)[1]);
+       /* ASC and ASCQ */
+       put_unaligned_le32(((asc << 24) | (ascq << 16)),
+           (&ctio->u.status1.sense_data)[3]);
+
+       /* Memory Barrier */
+       wmb();
+
+       qla2x00_start_iocbs(vha, vha->req);
+out:
+       return;
+}
+
 /* callback from target fabric module code */
 void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
 {
@@ -2261,7 +2354,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
                 */
                return -EAGAIN;
        } else
-               ha->tgt.cmds[h-1] = prm->cmd;
+               ha->tgt.cmds[h - 1] = prm->cmd;
 
        pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
        pkt->nport_handle = prm->cmd->loop_id;
@@ -2391,6 +2484,50 @@ static inline int qlt_has_data(struct qla_tgt_cmd *cmd)
        return cmd->bufflen > 0;
 }
 
+static void qlt_print_dif_err(struct qla_tgt_prm *prm)
+{
+       struct qla_tgt_cmd *cmd;
+       struct scsi_qla_host *vha;
+
+       /* asc 0x10=dif error */
+       if (prm->sense_buffer && (prm->sense_buffer[12] == 0x10)) {
+               cmd = prm->cmd;
+               vha = cmd->vha;
+               /* ASCQ */
+               switch (prm->sense_buffer[13]) {
+               case 1:
+                       ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                           "BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] "
+                           "se_cmd=%p tag[%x]",
+                           cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
+                           cmd->atio.u.isp24.exchange_addr);
+                       break;
+               case 2:
+                       ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                           "BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] "
+                           "se_cmd=%p tag[%x]",
+                           cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
+                           cmd->atio.u.isp24.exchange_addr);
+                       break;
+               case 3:
+                       ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                           "BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] "
+                           "se_cmd=%p tag[%x]",
+                           cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
+                           cmd->atio.u.isp24.exchange_addr);
+                       break;
+               default:
+                       ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                           "BE detected Dif ERR: lba[%llx|%lld] len[%x] "
+                           "se_cmd=%p tag[%x]",
+                           cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
+                           cmd->atio.u.isp24.exchange_addr);
+                       break;
+               }
+               ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xffff, cmd->cdb, 16);
+       }
+}
+
 /*
  * Called without ha->hardware_lock held
  */
@@ -2512,18 +2649,9 @@ skip_explict_conf:
                for (i = 0; i < prm->sense_buffer_len/4; i++)
                        ((uint32_t *)ctio->u.status1.sense_data)[i] =
                                cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
-#if 0
-               if (unlikely((prm->sense_buffer_len % 4) != 0)) {
-                       static int q;
-                       if (q < 10) {
-                               ql_dbg(ql_dbg_tgt, vha, 0xe04f,
-                                   "qla_target(%d): %d bytes of sense "
-                                   "lost", prm->tgt->ha->vp_idx,
-                                   prm->sense_buffer_len % 4);
-                               q++;
-                       }
-               }
-#endif
+
+               qlt_print_dif_err(prm);
+
        } else {
                ctio->u.status1.flags &=
                    ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
@@ -2537,19 +2665,9 @@ skip_explict_conf:
        /* Sense with len > 24, is it possible ??? */
 }
 
-
-
-/* diff  */
 static inline int
 qlt_hba_err_chk_enabled(struct se_cmd *se_cmd)
 {
-       /*
-        * Uncomment when corresponding SCSI changes are done.
-        *
-        if (!sp->cmd->prot_chk)
-        return 0;
-        *
-        */
        switch (se_cmd->prot_op) {
        case TARGET_PROT_DOUT_INSERT:
        case TARGET_PROT_DIN_STRIP:
@@ -2570,16 +2688,38 @@ qlt_hba_err_chk_enabled(struct se_cmd *se_cmd)
        return 0;
 }
 
+static inline int
+qla_tgt_ref_mask_check(struct se_cmd *se_cmd)
+{
+       switch (se_cmd->prot_op) {
+       case TARGET_PROT_DIN_INSERT:
+       case TARGET_PROT_DOUT_INSERT:
+       case TARGET_PROT_DIN_STRIP:
+       case TARGET_PROT_DOUT_STRIP:
+       case TARGET_PROT_DIN_PASS:
+       case TARGET_PROT_DOUT_PASS:
+           return 1;
+       default:
+           return 0;
+       }
+       return 0;
+}
+
 /*
- * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command
- *
+ * qla_tgt_set_dif_tags - Extract Ref and App tags from SCSI command
  */
-static inline void
-qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx)
+static void
+qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
+    uint16_t *pfw_prot_opts)
 {
+       struct se_cmd *se_cmd = &cmd->se_cmd;
        uint32_t lba = 0xffffffff & se_cmd->t_task_lba;
+       scsi_qla_host_t *vha = cmd->tgt->vha;
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t t32 = 0;
 
-       /* wait til Mode Sense/Select cmd, modepage Ah, subpage 2
+       /*
+        * wait till Mode Sense/Select cmd, modepage Ah, subpage 2
         * have been immplemented by TCM, before AppTag is avail.
         * Look for modesense_handlers[]
         */
@@ -2587,65 +2727,73 @@ qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx)
        ctx->app_tag_mask[0] = 0x0;
        ctx->app_tag_mask[1] = 0x0;
 
+       if (IS_PI_UNINIT_CAPABLE(ha)) {
+               if ((se_cmd->prot_type == TARGET_DIF_TYPE1_PROT) ||
+                   (se_cmd->prot_type == TARGET_DIF_TYPE2_PROT))
+                       *pfw_prot_opts |= PO_DIS_VALD_APP_ESC;
+               else if (se_cmd->prot_type == TARGET_DIF_TYPE3_PROT)
+                       *pfw_prot_opts |= PO_DIS_VALD_APP_REF_ESC;
+       }
+
+       t32 = ha->tgt.tgt_ops->get_dif_tags(cmd, pfw_prot_opts);
+
        switch (se_cmd->prot_type) {
        case TARGET_DIF_TYPE0_PROT:
                /*
-                * No check for ql2xenablehba_err_chk, as it would be an
-                * I/O error if hba tag generation is not done.
+                * No check for ql2xenablehba_err_chk, as it
+                * would be an I/O error if hba tag generation
+                * is not done.
                 */
                ctx->ref_tag = cpu_to_le32(lba);
-
-               if (!qlt_hba_err_chk_enabled(se_cmd))
-                       break;
-
                /* enable ALL bytes of the ref tag */
                ctx->ref_tag_mask[0] = 0xff;
                ctx->ref_tag_mask[1] = 0xff;
                ctx->ref_tag_mask[2] = 0xff;
                ctx->ref_tag_mask[3] = 0xff;
                break;
-       /*
-        * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and
-        * 16 bit app tag.
-        */
        case TARGET_DIF_TYPE1_PROT:
-               ctx->ref_tag = cpu_to_le32(lba);
-
-               if (!qlt_hba_err_chk_enabled(se_cmd))
-                       break;
-
-               /* enable ALL bytes of the ref tag */
-               ctx->ref_tag_mask[0] = 0xff;
-               ctx->ref_tag_mask[1] = 0xff;
-               ctx->ref_tag_mask[2] = 0xff;
-               ctx->ref_tag_mask[3] = 0xff;
-               break;
-       /*
-        * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to
-        * match LBA in CDB + N
-        */
+           /*
+            * For TYPE 1 protection: 16 bit GUARD tag, 32 bit
+            * REF tag, and 16 bit app tag.
+            */
+           ctx->ref_tag = cpu_to_le32(lba);
+           if (!qla_tgt_ref_mask_check(se_cmd) ||
+               !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
+                   *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
+                   break;
+           }
+           /* enable ALL bytes of the ref tag */
+           ctx->ref_tag_mask[0] = 0xff;
+           ctx->ref_tag_mask[1] = 0xff;
+           ctx->ref_tag_mask[2] = 0xff;
+           ctx->ref_tag_mask[3] = 0xff;
+           break;
        case TARGET_DIF_TYPE2_PROT:
-               ctx->ref_tag = cpu_to_le32(lba);
-
-               if (!qlt_hba_err_chk_enabled(se_cmd))
-                       break;
-
-               /* enable ALL bytes of the ref tag */
-               ctx->ref_tag_mask[0] = 0xff;
-               ctx->ref_tag_mask[1] = 0xff;
-               ctx->ref_tag_mask[2] = 0xff;
-               ctx->ref_tag_mask[3] = 0xff;
-               break;
-
-       /* For Type 3 protection: 16 bit GUARD only */
+           /*
+            * For TYPE 2 protection: 16 bit GUARD + 32 bit REF
+            * tag has to match LBA in CDB + N
+            */
+           ctx->ref_tag = cpu_to_le32(lba);
+           if (!qla_tgt_ref_mask_check(se_cmd) ||
+               !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
+                   *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
+                   break;
+           }
+           /* enable ALL bytes of the ref tag */
+           ctx->ref_tag_mask[0] = 0xff;
+           ctx->ref_tag_mask[1] = 0xff;
+           ctx->ref_tag_mask[2] = 0xff;
+           ctx->ref_tag_mask[3] = 0xff;
+           break;
        case TARGET_DIF_TYPE3_PROT:
-               ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] =
-                       ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00;
-               break;
+           /* For TYPE 3 protection: 16 bit GUARD only */
+           *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
+           ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] =
+               ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00;
+           break;
        }
 }
 
-
 static inline int
 qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
 {
@@ -2664,6 +2812,7 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
        struct se_cmd           *se_cmd = &cmd->se_cmd;
        uint32_t h;
        struct atio_from_isp *atio = &prm->cmd->atio;
+       struct qla_tc_param     tc;
        uint16_t t16;
 
        ha = vha->hw;
@@ -2689,16 +2838,15 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
        case TARGET_PROT_DIN_INSERT:
        case TARGET_PROT_DOUT_STRIP:
                transfer_length = data_bytes;
-               data_bytes += dif_bytes;
+               if (cmd->prot_sg_cnt)
+                       data_bytes += dif_bytes;
                break;
-
        case TARGET_PROT_DIN_STRIP:
        case TARGET_PROT_DOUT_INSERT:
        case TARGET_PROT_DIN_PASS:
        case TARGET_PROT_DOUT_PASS:
                transfer_length = data_bytes + dif_bytes;
                break;
-
        default:
                BUG();
                break;
@@ -2734,7 +2882,6 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
                break;
        }
 
-
        /* ---- PKT ---- */
        /* Update entry type to indicate Command Type CRC_2 IOCB */
        pkt->entry_type  = CTIO_CRC2;
@@ -2752,9 +2899,8 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
        } else
                ha->tgt.cmds[h-1] = prm->cmd;
 
-
        pkt->handle  = h | CTIO_COMPLETION_HANDLE_MARK;
-       pkt->nport_handle = prm->cmd->loop_id;
+       pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
        pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
        pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
        pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
@@ -2775,12 +2921,10 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
        else if (cmd->dma_data_direction == DMA_FROM_DEVICE)
                pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT);
 
-
        pkt->dseg_count = prm->tot_dsds;
        /* Fibre channel byte count */
        pkt->transfer_length = cpu_to_le32(transfer_length);
 
-
        /* ----- CRC context -------- */
 
        /* Allocate CRC context from global pool */
@@ -2800,13 +2944,12 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
        /* Set handle */
        crc_ctx_pkt->handle = pkt->handle;
 
-       qlt_set_t10dif_tags(se_cmd, crc_ctx_pkt);
+       qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts);
 
        pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
        pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
        pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
 
-
        if (!bundling) {
                cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
        } else {
@@ -2827,16 +2970,24 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
        crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes);
        crc_ctx_pkt->guard_seed = cpu_to_le16(0);
 
+       memset((uint8_t *)&tc, 0 , sizeof(tc));
+       tc.vha = vha;
+       tc.blk_sz = cmd->blk_sz;
+       tc.bufflen = cmd->bufflen;
+       tc.sg = cmd->sg;
+       tc.prot_sg = cmd->prot_sg;
+       tc.ctx = crc_ctx_pkt;
+       tc.ctx_dsd_alloced = &cmd->ctx_dsd_alloced;
 
        /* Walks data segments */
        pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR);
 
        if (!bundling && prm->prot_seg_cnt) {
                if (qla24xx_walk_and_build_sglist_no_difb(ha, NULL, cur_dsd,
-                       prm->tot_dsds, cmd))
+                       prm->tot_dsds, &tc))
                        goto crc_queuing_error;
        } else if (qla24xx_walk_and_build_sglist(ha, NULL, cur_dsd,
-               (prm->tot_dsds - prm->prot_seg_cnt), cmd))
+               (prm->tot_dsds - prm->prot_seg_cnt), &tc))
                goto crc_queuing_error;
 
        if (bundling && prm->prot_seg_cnt) {
@@ -2845,18 +2996,18 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
 
                cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
                if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd,
-                       prm->prot_seg_cnt, cmd))
+                       prm->prot_seg_cnt, &tc))
                        goto crc_queuing_error;
        }
        return QLA_SUCCESS;
 
 crc_queuing_error:
        /* Cleanup will be performed by the caller */
+       vha->hw->tgt.cmds[h - 1] = NULL;
 
        return QLA_FUNCTION_FAILED;
 }
 
-
 /*
  * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and *
  * QLA_TGT_XMIT_STATUS for >= 24xx silicon
@@ -2906,7 +3057,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
        else
                vha->tgt_counters.core_qla_que_buf++;
 
-       if (!vha->flags.online || cmd->reset_count != ha->chip_reset) {
+       if (!ha->flags.fw_started || cmd->reset_count != ha->chip_reset) {
                /*
                 * Either the port is not online or this request was from
                 * previous life, just abort the processing.
@@ -3047,7 +3198,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
-       if (!vha->flags.online || (cmd->reset_count != ha->chip_reset) ||
+       if (!ha->flags.fw_started || (cmd->reset_count != ha->chip_reset) ||
            (cmd->sess && cmd->sess->deleted)) {
                /*
                 * Either the port is not online or this request was from
@@ -3104,139 +3255,113 @@ EXPORT_SYMBOL(qlt_rdy_to_xfer);
 
 
 /*
- * Checks the guard or meta-data for the type of error
- * detected by the HBA.
+ * it is assumed either hardware_lock or qpair lock is held.
  */
-static inline int
+static void
 qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
-               struct ctio_crc_from_fw *sts)
+       struct ctio_crc_from_fw *sts)
 {
        uint8_t         *ap = &sts->actual_dif[0];
        uint8_t         *ep = &sts->expected_dif[0];
-       uint32_t        e_ref_tag, a_ref_tag;
-       uint16_t        e_app_tag, a_app_tag;
-       uint16_t        e_guard, a_guard;
        uint64_t        lba = cmd->se_cmd.t_task_lba;
+       uint8_t scsi_status, sense_key, asc, ascq;
+       unsigned long flags;
 
-       a_guard   = be16_to_cpu(*(uint16_t *)(ap + 0));
-       a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
-       a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
-
-       e_guard   = be16_to_cpu(*(uint16_t *)(ep + 0));
-       e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
-       e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
-
-       ql_dbg(ql_dbg_tgt, vha, 0xe075,
-           "iocb(s) %p Returned STATUS.\n", sts);
-
-       ql_dbg(ql_dbg_tgt, vha, 0xf075,
-           "dif check TGT cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x]\n",
-           cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
-           a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, a_guard, e_guard);
-
-       /*
-        * Ignore sector if:
-        * For type     3: ref & app tag is all 'f's
-        * For type 0,1,2: app tag is all 'f's
-        */
-       if ((a_app_tag == 0xffff) &&
-           ((cmd->se_cmd.prot_type != TARGET_DIF_TYPE3_PROT) ||
-            (a_ref_tag == 0xffffffff))) {
-               uint32_t blocks_done;
-
-               /* 2TB boundary case covered automatically with this */
-               blocks_done = e_ref_tag - (uint32_t)lba + 1;
-               cmd->se_cmd.bad_sector = e_ref_tag;
-               cmd->se_cmd.pi_err = 0;
-               ql_dbg(ql_dbg_tgt, vha, 0xf074,
-                       "need to return scsi good\n");
-
-               /* Update protection tag */
-               if (cmd->prot_sg_cnt) {
-                       uint32_t i, k = 0, num_ent;
-                       struct scatterlist *sg, *sgl;
-
-
-                       sgl = cmd->prot_sg;
-
-                       /* Patch the corresponding protection tags */
-                       for_each_sg(sgl, sg, cmd->prot_sg_cnt, i) {
-                               num_ent = sg_dma_len(sg) / 8;
-                               if (k + num_ent < blocks_done) {
-                                       k += num_ent;
-                                       continue;
-                               }
-                               k = blocks_done;
-                               break;
-                       }
+       cmd->trc_flags |= TRC_DIF_ERR;
 
-                       if (k != blocks_done) {
-                               ql_log(ql_log_warn, vha, 0xf076,
-                                   "unexpected tag values tag:lba=%u:%llu)\n",
-                                   e_ref_tag, (unsigned long long)lba);
-                               goto out;
-                       }
+       cmd->a_guard   = be16_to_cpu(*(uint16_t *)(ap + 0));
+       cmd->a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
+       cmd->a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
 
-#if 0
-                       struct sd_dif_tuple *spt;
-                       /* TODO:
-                        * This section came from initiator. Is it valid here?
-                        * should ulp be override with actual val???
-                        */
-                       spt = page_address(sg_page(sg)) + sg->offset;
-                       spt += j;
+       cmd->e_guard   = be16_to_cpu(*(uint16_t *)(ep + 0));
+       cmd->e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
+       cmd->e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
 
-                       spt->app_tag = 0xffff;
-                       if (cmd->se_cmd.prot_type == SCSI_PROT_DIF_TYPE3)
-                               spt->ref_tag = 0xffffffff;
-#endif
-               }
+       ql_dbg(ql_dbg_tgt_dif, vha, 0xf075,
+           "%s: aborted %d state %d\n", __func__, cmd->aborted, cmd->state);
 
-               return 0;
-       }
+       scsi_status = sense_key = asc = ascq = 0;
 
-       /* check guard */
-       if (e_guard != a_guard) {
-               cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
-               cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba;
-
-               ql_log(ql_log_warn, vha, 0xe076,
-                   "Guard ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
-                   cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
-                   a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
-                   a_guard, e_guard, cmd);
-               goto out;
+       /* check appl tag */
+       if (cmd->e_app_tag != cmd->a_app_tag) {
+               ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                       "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
+                       "Ref[%x|%x], App[%x|%x], "
+                       "Guard [%x|%x] cmd=%p ox_id[%04x]",
+                       cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
+                       cmd->a_ref_tag, cmd->e_ref_tag,
+                       cmd->a_app_tag, cmd->e_app_tag,
+                       cmd->a_guard, cmd->e_guard,
+                       cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
+
+               cmd->dif_err_code = DIF_ERR_APP;
+               scsi_status = SAM_STAT_CHECK_CONDITION;
+               sense_key = ABORTED_COMMAND;
+               asc = 0x10;
+               ascq = 0x2;
        }
 
        /* check ref tag */
-       if (e_ref_tag != a_ref_tag) {
-               cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
-               cmd->se_cmd.bad_sector = e_ref_tag;
-
-               ql_log(ql_log_warn, vha, 0xe077,
-                       "Ref Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
-                       cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
-                       a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
-                       a_guard, e_guard, cmd);
+       if (cmd->e_ref_tag != cmd->a_ref_tag) {
+               ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                       "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
+                       "Ref[%x|%x], App[%x|%x], "
+                       "Guard[%x|%x] cmd=%p ox_id[%04x] ",
+                       cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
+                       cmd->a_ref_tag, cmd->e_ref_tag,
+                       cmd->a_app_tag, cmd->e_app_tag,
+                       cmd->a_guard, cmd->e_guard,
+                       cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
+
+               cmd->dif_err_code = DIF_ERR_REF;
+               scsi_status = SAM_STAT_CHECK_CONDITION;
+               sense_key = ABORTED_COMMAND;
+               asc = 0x10;
+               ascq = 0x3;
                goto out;
        }
 
-       /* check appl tag */
-       if (e_app_tag != a_app_tag) {
-               cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
-               cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba;
-
-               ql_log(ql_log_warn, vha, 0xe078,
-                       "App Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
-                       cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
-                       a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
-                       a_guard, e_guard, cmd);
-               goto out;
+       /* check guard */
+       if (cmd->e_guard != cmd->a_guard) {
+               ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                       "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
+                       "Ref[%x|%x], App[%x|%x], "
+                       "Guard [%x|%x] cmd=%p ox_id[%04x]",
+                       cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
+                       cmd->a_ref_tag, cmd->e_ref_tag,
+                       cmd->a_app_tag, cmd->e_app_tag,
+                       cmd->a_guard, cmd->e_guard,
+                       cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
+               cmd->dif_err_code = DIF_ERR_GRD;
+               scsi_status = SAM_STAT_CHECK_CONDITION;
+               sense_key = ABORTED_COMMAND;
+               asc = 0x10;
+               ascq = 0x1;
        }
 out:
-       return 1;
-}
+       switch (cmd->state) {
+       case QLA_TGT_STATE_NEED_DATA:
+               /* handle_data will load DIF error code  */
+               cmd->state = QLA_TGT_STATE_DATA_IN;
+               vha->hw->tgt.tgt_ops->handle_data(cmd);
+               break;
+       default:
+               spin_lock_irqsave(&cmd->cmd_lock, flags);
+               if (cmd->aborted) {
+                       spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+                       vha->hw->tgt.tgt_ops->free_cmd(cmd);
+                       break;
+               }
+               spin_unlock_irqrestore(&cmd->cmd_lock, flags);
 
+               qlt_send_resp_ctio(vha, cmd, scsi_status, sense_key, asc, ascq);
+               /* assume scsi status gets out on the wire.
+                * Will not wait for completion.
+                */
+               vha->hw->tgt.tgt_ops->free_cmd(cmd);
+               break;
+       }
+}
 
 /* If hardware_lock held on entry, might drop it, then reaquire */
 /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
@@ -3251,7 +3376,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
        ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c,
            "Sending TERM ELS CTIO (ha=%p)\n", ha);
 
-       pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
+       pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL);
        if (pkt == NULL) {
                ql_dbg(ql_dbg_tgt, vha, 0xe080,
                    "qla_target(%d): %s failed: unable to allocate "
@@ -3543,6 +3668,16 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
 {
        int term = 0;
 
+       if (cmd->se_cmd.prot_op)
+               ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+                   "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] "
+                   "se_cmd=%p tag[%x] op %#x/%s",
+                    cmd->lba, cmd->lba,
+                    cmd->num_blks, &cmd->se_cmd,
+                    cmd->atio.u.isp24.exchange_addr,
+                    cmd->se_cmd.prot_op,
+                    prot_op_str(cmd->se_cmd.prot_op));
+
        if (ctio != NULL) {
                struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio;
                term = !(c->flags &
@@ -3760,32 +3895,15 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
                        struct ctio_crc_from_fw *crc =
                                (struct ctio_crc_from_fw *)ctio;
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073,
-                           "qla_target(%d): CTIO with DIF_ERROR status %x received (state %x, se_cmd %p) actual_dif[0x%llx] expect_dif[0x%llx]\n",
+                           "qla_target(%d): CTIO with DIF_ERROR status %x "
+                           "received (state %x, ulp_cmd %p) actual_dif[0x%llx] "
+                           "expect_dif[0x%llx]\n",
                            vha->vp_idx, status, cmd->state, se_cmd,
                            *((u64 *)&crc->actual_dif[0]),
                            *((u64 *)&crc->expected_dif[0]));
 
-                       if (qlt_handle_dif_error(vha, cmd, ctio)) {
-                               if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
-                                       /* scsi Write/xfer rdy complete */
-                                       goto skip_term;
-                               } else {
-                                       /* scsi read/xmit respond complete
-                                        * call handle dif to send scsi status
-                                        * rather than terminate exchange.
-                                        */
-                                       cmd->state = QLA_TGT_STATE_PROCESSED;
-                                       ha->tgt.tgt_ops->handle_dif_err(cmd);
-                                       return;
-                               }
-                       } else {
-                               /* Need to generate a SCSI good completion.
-                                * because FW did not send scsi status.
-                                */
-                               status = 0;
-                               goto skip_term;
-                       }
-                       break;
+                       qlt_handle_dif_error(vha, cmd, ctio);
+                       return;
                }
                default:
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
@@ -3808,7 +3926,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
                                return;
                }
        }
-skip_term:
 
        if (cmd->state == QLA_TGT_STATE_PROCESSED) {
                cmd->trc_flags |= TRC_CTIO_DONE;
@@ -4584,7 +4701,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
                }
 
                if (sess != NULL) {
-                       if (sess->fw_login_state == DSC_LS_PLOGI_PEND) {
+                       if (sess->fw_login_state != DSC_LS_PLOGI_PEND &&
+                           sess->fw_login_state != DSC_LS_PLOGI_COMP) {
                                /*
                                 * Impatient initiator sent PRLI before last
                                 * PLOGI could finish. Will force him to re-try,
@@ -4623,15 +4741,23 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 
                /* Make session global (not used in fabric mode) */
                if (ha->current_topology != ISP_CFG_F) {
-                       set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
-                       set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
-                       qla2xxx_wake_dpc(vha);
+                       if (sess) {
+                               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                                   "%s %d %8phC post nack\n",
+                                   __func__, __LINE__, sess->port_name);
+                               qla24xx_post_nack_work(vha, sess, iocb,
+                                       SRB_NACK_PRLI);
+                               res = 0;
+                       } else {
+                               set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+                               set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+                               qla2xxx_wake_dpc(vha);
+                       }
                } else {
                        if (sess) {
                                ql_dbg(ql_dbg_disc, vha, 0xffff,
-                                          "%s %d %8phC post nack\n",
-                                          __func__, __LINE__, sess->port_name);
-
+                                   "%s %d %8phC post nack\n",
+                                   __func__, __LINE__, sess->port_name);
                                qla24xx_post_nack_work(vha, sess, iocb,
                                        SRB_NACK_PRLI);
                                res = 0;
@@ -4639,7 +4765,6 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
                }
                break;
 
-
        case ELS_TPRLO:
                if (le16_to_cpu(iocb->u.isp24.flags) &
                        NOTIFY24XX_FLAGS_GLOBAL_TPRLO) {
@@ -5079,16 +5204,22 @@ qlt_send_busy(struct scsi_qla_host *vha,
 
 static int
 qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha,
-       struct atio_from_isp *atio)
+       struct atio_from_isp *atio, bool ha_locked)
 {
        struct qla_hw_data *ha = vha->hw;
        uint16_t status;
+       unsigned long flags;
 
        if (ha->tgt.num_pend_cmds < Q_FULL_THRESH_HOLD(ha))
                return 0;
 
+       if (!ha_locked)
+               spin_lock_irqsave(&ha->hardware_lock, flags);
        status = temp_sam_status;
        qlt_send_busy(vha, atio, status);
+       if (!ha_locked)
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
        return 1;
 }
 
@@ -5103,7 +5234,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
        unsigned long flags;
 
        if (unlikely(tgt == NULL)) {
-               ql_dbg(ql_dbg_io, vha, 0x3064,
+               ql_dbg(ql_dbg_tgt, vha, 0x3064,
                    "ATIO pkt, but no tgt (ha %p)", ha);
                return;
        }
@@ -5133,7 +5264,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
 
 
                if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) {
-                       rc = qlt_chk_qfull_thresh_hold(vha, atio);
+                       rc = qlt_chk_qfull_thresh_hold(vha, atio, ha_locked);
                        if (rc != 0) {
                                tgt->atio_irq_cmd_count--;
                                return;
@@ -5256,7 +5387,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
                        break;
                }
 
-               rc = qlt_chk_qfull_thresh_hold(vha, atio);
+               rc = qlt_chk_qfull_thresh_hold(vha, atio, true);
                if (rc != 0) {
                        tgt->irq_cmd_count--;
                        return;
@@ -5531,7 +5662,7 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
 
        fcport->loop_id = loop_id;
 
-       rc = qla2x00_get_port_database(vha, fcport, 0);
+       rc = qla24xx_gpdb_wait(vha, fcport, 0);
        if (rc != QLA_SUCCESS) {
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf070,
                    "qla_target(%d): Failed to retrieve fcport "
@@ -5713,30 +5844,23 @@ static void qlt_abort_work(struct qla_tgt *tgt,
                }
        }
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
-
-       if (tgt->tgt_stop)
-               goto out_term;
-
        rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess);
+       ha->tgt.tgt_ops->put_sess(sess);
+       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
+
        if (rc != 0)
                goto out_term;
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-       if (sess)
-               ha->tgt.tgt_ops->put_sess(sess);
-       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
        return;
 
 out_term2:
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       if (sess)
+               ha->tgt.tgt_ops->put_sess(sess);
+       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
 
 out_term:
+       spin_lock_irqsave(&ha->hardware_lock, flags);
        qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-       if (sess)
-               ha->tgt.tgt_ops->put_sess(sess);
-       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
 }
 
 static void qlt_tmr_work(struct qla_tgt *tgt,
@@ -5756,7 +5880,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
        spin_lock_irqsave(&ha->tgt.sess_lock, flags);
 
        if (tgt->tgt_stop)
-               goto out_term;
+               goto out_term2;
 
        s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id;
        sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
@@ -5768,11 +5892,11 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
 
                spin_lock_irqsave(&ha->tgt.sess_lock, flags);
                if (!sess)
-                       goto out_term;
+                       goto out_term2;
        } else {
                if (sess->deleted) {
                        sess = NULL;
-                       goto out_term;
+                       goto out_term2;
                }
 
                if (!kref_get_unless_zero(&sess->sess_kref)) {
@@ -5780,7 +5904,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
                            "%s: kref_get fail %8phC\n",
                             __func__, sess->port_name);
                        sess = NULL;
-                       goto out_term;
+                       goto out_term2;
                }
        }
 
@@ -5790,17 +5914,19 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
        unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
 
        rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
-       if (rc != 0)
-               goto out_term;
-
        ha->tgt.tgt_ops->put_sess(sess);
        spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+       if (rc != 0)
+               goto out_term;
        return;
 
+out_term2:
+       if (sess)
+               ha->tgt.tgt_ops->put_sess(sess);
+       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 out_term:
        qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
-       ha->tgt.tgt_ops->put_sess(sess);
-       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 }
 
 static void qlt_sess_work_fn(struct work_struct *work)
@@ -5893,13 +6019,13 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
        tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
        tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
 
-       if (base_vha->fc_vport)
-               return 0;
-
        mutex_lock(&qla_tgt_mutex);
        list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
        mutex_unlock(&qla_tgt_mutex);
 
+       if (ha->tgt.tgt_ops && ha->tgt.tgt_ops->add_target)
+               ha->tgt.tgt_ops->add_target(base_vha);
+
        return 0;
 }
 
@@ -5928,6 +6054,17 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
        return 0;
 }
 
+void qlt_remove_target_resources(struct qla_hw_data *ha)
+{
+       struct scsi_qla_host *node;
+       u32 key = 0;
+
+       btree_for_each_safe32(&ha->tgt.host_map, key, node)
+               btree_remove32(&ha->tgt.host_map, key);
+
+       btree_destroy32(&ha->tgt.host_map);
+}
+
 static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
        unsigned char *b)
 {
@@ -6234,7 +6371,7 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
        struct atio_from_isp *pkt;
        int cnt, i;
 
-       if (!vha->flags.online)
+       if (!ha->flags.fw_started)
                return;
 
        while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
@@ -6581,6 +6718,8 @@ qlt_modify_vp_config(struct scsi_qla_host *vha,
 void
 qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
 {
+       int rc;
+
        if (!QLA_TGT_MODE_ENABLED())
                return;
 
@@ -6600,6 +6739,13 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
            qlt_unknown_atio_work_fn);
 
        qlt_clear_mode(base_vha);
+
+       rc = btree_init32(&ha->tgt.host_map);
+       if (rc)
+               ql_log(ql_log_info, base_vha, 0xffff,
+                   "Unable to initialize ha->host_map btree\n");
+
+       qlt_update_vp_map(base_vha, SET_VP_IDX);
 }
 
 irqreturn_t
@@ -6642,6 +6788,8 @@ qlt_handle_abts_recv_work(struct work_struct *work)
        spin_lock_irqsave(&ha->hardware_lock, flags);
        qlt_response_pkt_all_vps(vha, (response_t *)&op->atio);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+       kfree(op);
 }
 
 void
@@ -6706,25 +6854,69 @@ qlt_mem_free(struct qla_hw_data *ha)
 void
 qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
 {
+       void *slot;
+       u32 key;
+       int rc;
+
        if (!QLA_TGT_MODE_ENABLED())
                return;
 
+       key = vha->d_id.b24;
+
        switch (cmd) {
        case SET_VP_IDX:
                vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
                break;
        case SET_AL_PA:
-               vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = vha->vp_idx;
+               slot = btree_lookup32(&vha->hw->tgt.host_map, key);
+               if (!slot) {
+                       ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+                           "Save vha in host_map %p %06x\n", vha, key);
+                       rc = btree_insert32(&vha->hw->tgt.host_map,
+                               key, vha, GFP_ATOMIC);
+                       if (rc)
+                               ql_log(ql_log_info, vha, 0xffff,
+                                   "Unable to insert s_id into host_map: %06x\n",
+                                   key);
+                       return;
+               }
+               ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+                       "replace existing vha in host_map %p %06x\n", vha, key);
+               btree_update32(&vha->hw->tgt.host_map, key, vha);
                break;
        case RESET_VP_IDX:
                vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
                break;
        case RESET_AL_PA:
-               vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = 0;
+               ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+                  "clear vha in host_map %p %06x\n", vha, key);
+               slot = btree_lookup32(&vha->hw->tgt.host_map, key);
+               if (slot)
+                       btree_remove32(&vha->hw->tgt.host_map, key);
+               vha->d_id.b24 = 0;
                break;
        }
 }
 
+void qlt_update_host_map(struct scsi_qla_host *vha, port_id_t id)
+{
+       unsigned long flags;
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!vha->d_id.b24) {
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               vha->d_id = id;
+               qlt_update_vp_map(vha, SET_AL_PA);
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+       } else if (vha->d_id.b24 != id.b24) {
+               spin_lock_irqsave(&ha->vport_slock, flags);
+               qlt_update_vp_map(vha, RESET_AL_PA);
+               vha->d_id = id;
+               qlt_update_vp_map(vha, SET_AL_PA);
+               spin_unlock_irqrestore(&ha->vport_slock, flags);
+       }
+}
+
 static int __init qlt_parse_ini_mode(void)
 {
        if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0)
index a7f90dcaae37d3eaad551544c6151785faf84cb9..d64420251194eb5fa634a36699ecf07c69e09edd 100644 (file)
@@ -378,6 +378,14 @@ static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
        atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
 }
 
+static inline int get_datalen_for_atio(struct atio_from_isp *atio)
+{
+       int len = atio->u.isp24.fcp_cmnd.add_cdb_len;
+
+       return (be32_to_cpu(get_unaligned((uint32_t *)
+           &atio->u.isp24.fcp_cmnd.add_cdb[len * 4])));
+}
+
 #define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
 
 /*
@@ -667,7 +675,6 @@ struct qla_tgt_func_tmpl {
        int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
                        unsigned char *, uint32_t, int, int, int);
        void (*handle_data)(struct qla_tgt_cmd *);
-       void (*handle_dif_err)(struct qla_tgt_cmd *);
        int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t,
                        uint32_t);
        void (*free_cmd)(struct qla_tgt_cmd *);
@@ -684,6 +691,9 @@ struct qla_tgt_func_tmpl {
        void (*clear_nacl_from_fcport_map)(struct fc_port *);
        void (*put_sess)(struct fc_port *);
        void (*shutdown_sess)(struct fc_port *);
+       int (*get_dif_tags)(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts);
+       int (*chk_dif_tags)(uint32_t tag);
+       void (*add_target)(struct scsi_qla_host *);
 };
 
 int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
@@ -720,8 +730,8 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
 #define QLA_TGT_ABORT_ALL               0xFFFE
 #define QLA_TGT_NEXUS_LOSS_SESS         0xFFFD
 #define QLA_TGT_NEXUS_LOSS              0xFFFC
-#define QLA_TGT_ABTS                                   0xFFFB
-#define QLA_TGT_2G_ABORT_TASK                  0xFFFA
+#define QLA_TGT_ABTS                   0xFFFB
+#define QLA_TGT_2G_ABORT_TASK          0xFFFA
 
 /* Notify Acknowledge flags */
 #define NOTIFY_ACK_RES_COUNT        BIT_8
@@ -845,6 +855,7 @@ enum trace_flags {
        TRC_CMD_FREE = BIT_17,
        TRC_DATA_IN = BIT_18,
        TRC_ABORT = BIT_19,
+       TRC_DIF_ERR = BIT_20,
 };
 
 struct qla_tgt_cmd {
@@ -862,7 +873,6 @@ struct qla_tgt_cmd {
        unsigned int sg_mapped:1;
        unsigned int free_sg:1;
        unsigned int write_data_transferred:1;
-       unsigned int ctx_dsd_alloced:1;
        unsigned int q_full:1;
        unsigned int term_exchg:1;
        unsigned int cmd_sent_to_fw:1;
@@ -885,11 +895,25 @@ struct qla_tgt_cmd {
        struct list_head cmd_list;
 
        struct atio_from_isp atio;
-       /* t10dif */
+
+       uint8_t ctx_dsd_alloced;
+
+       /* T10-DIF */
+#define DIF_ERR_NONE 0
+#define DIF_ERR_GRD 1
+#define DIF_ERR_REF 2
+#define DIF_ERR_APP 3
+       int8_t dif_err_code;
        struct scatterlist *prot_sg;
        uint32_t prot_sg_cnt;
-       uint32_t blk_sz;
+       uint32_t blk_sz, num_blks;
+       uint8_t scsi_status, sense_key, asc, ascq;
+
        struct crc_context *ctx;
+       uint8_t         *cdb;
+       uint64_t        lba;
+       uint16_t        a_guard, e_guard, a_app_tag, e_app_tag;
+       uint32_t        a_ref_tag, e_ref_tag;
 
        uint64_t jiffies_at_alloc;
        uint64_t jiffies_at_free;
@@ -1053,4 +1077,7 @@ extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
 extern void qlt_logo_completion_handler(fc_port_t *, int);
 extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
 
+void qlt_send_resp_ctio(scsi_qla_host_t *, struct qla_tgt_cmd *, uint8_t,
+    uint8_t, uint8_t, uint8_t);
+
 #endif /* __QLA_TARGET_H */
index 3cb1964b7786e4e2add64d7c8f5788fd73b90134..45bc84e8e3bf50f798616de47a2f348d684222b4 100644 (file)
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.07.00.38-k"
+#define QLA2XXX_VERSION      "9.00.00.00-k"
 
-#define QLA_DRIVER_MAJOR_VER   8
-#define QLA_DRIVER_MINOR_VER   7
+#define QLA_DRIVER_MAJOR_VER   9
+#define QLA_DRIVER_MINOR_VER   0
 #define QLA_DRIVER_PATCH_VER   0
 #define QLA_DRIVER_BETA_VER    0
index 8e8ab0fa9672a6674d3cc9556beeccc44dfc70b2..7443e4efa3aed461f225f6b04bae9223f615dd0b 100644 (file)
@@ -531,6 +531,24 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
                        return;
                }
 
+               switch (cmd->dif_err_code) {
+               case DIF_ERR_GRD:
+                       cmd->se_cmd.pi_err =
+                           TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
+                       break;
+               case DIF_ERR_REF:
+                       cmd->se_cmd.pi_err =
+                           TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
+                       break;
+               case DIF_ERR_APP:
+                       cmd->se_cmd.pi_err =
+                           TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
+                       break;
+               case DIF_ERR_NONE:
+               default:
+                       break;
+               }
+
                if (cmd->se_cmd.pi_err)
                        transport_generic_request_failure(&cmd->se_cmd,
                                cmd->se_cmd.pi_err);
@@ -555,25 +573,23 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
        queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
 }
 
-static void tcm_qla2xxx_handle_dif_work(struct work_struct *work)
+static int tcm_qla2xxx_chk_dif_tags(uint32_t tag)
 {
-       struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
-
-       /* take an extra kref to prevent cmd free too early.
-        * need to wait for SCSI status/check condition to
-        * finish responding generate by transport_generic_request_failure.
-        */
-       kref_get(&cmd->se_cmd.cmd_kref);
-       transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err);
+       return 0;
 }
 
-/*
- * Called from qla_target.c:qlt_do_ctio_completion()
- */
-static void tcm_qla2xxx_handle_dif_err(struct qla_tgt_cmd *cmd)
+static int tcm_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd,
+    uint16_t *pfw_prot_opts)
 {
-       INIT_WORK(&cmd->work, tcm_qla2xxx_handle_dif_work);
-       queue_work(tcm_qla2xxx_free_wq, &cmd->work);
+       struct se_cmd *se_cmd = &cmd->se_cmd;
+
+       if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
+               *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK;
+
+       if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_APPTAG))
+               *pfw_prot_opts |= PO_DIS_APP_TAG_VALD;
+
+       return 0;
 }
 
 /*
@@ -1610,7 +1626,6 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
 static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
        .handle_cmd             = tcm_qla2xxx_handle_cmd,
        .handle_data            = tcm_qla2xxx_handle_data,
-       .handle_dif_err         = tcm_qla2xxx_handle_dif_err,
        .handle_tmr             = tcm_qla2xxx_handle_tmr,
        .free_cmd               = tcm_qla2xxx_free_cmd,
        .free_mcmd              = tcm_qla2xxx_free_mcmd,
@@ -1622,6 +1637,8 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
        .clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map,
        .put_sess               = tcm_qla2xxx_put_sess,
        .shutdown_sess          = tcm_qla2xxx_shutdown_sess,
+       .get_dif_tags           = tcm_qla2xxx_dif_tags,
+       .chk_dif_tags           = tcm_qla2xxx_chk_dif_tags,
 };
 
 static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)
index ba2286652ff647f285761e046f3699bed5c39eba..19125d72f322c934d84d2d71c748ca9c08418846 100644 (file)
@@ -2932,6 +2932,8 @@ EXPORT_SYMBOL(scsi_target_resume);
 /**
  * scsi_internal_device_block - internal function to put a device temporarily into the SDEV_BLOCK state
  * @sdev:      device to block
+ * @wait:      Whether or not to wait until ongoing .queuecommand() /
+ *             .queue_rq() calls have finished.
  *
  * Block request made by scsi lld's to temporarily stop all
  * scsi commands on the specified device. May sleep.
@@ -2949,7 +2951,7 @@ EXPORT_SYMBOL(scsi_target_resume);
  * remove the rport mutex lock and unlock calls from srp_queuecommand().
  */
 int
-scsi_internal_device_block(struct scsi_device *sdev)
+scsi_internal_device_block(struct scsi_device *sdev, bool wait)
 {
        struct request_queue *q = sdev->request_queue;
        unsigned long flags;
@@ -2969,12 +2971,16 @@ scsi_internal_device_block(struct scsi_device *sdev)
         * request queue. 
         */
        if (q->mq_ops) {
-               blk_mq_quiesce_queue(q);
+               if (wait)
+                       blk_mq_quiesce_queue(q);
+               else
+                       blk_mq_stop_hw_queues(q);
        } else {
                spin_lock_irqsave(q->queue_lock, flags);
                blk_stop_queue(q);
                spin_unlock_irqrestore(q->queue_lock, flags);
-               scsi_wait_for_queuecommand(sdev);
+               if (wait)
+                       scsi_wait_for_queuecommand(sdev);
        }
 
        return 0;
@@ -3036,7 +3042,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
 static void
 device_block(struct scsi_device *sdev, void *data)
 {
-       scsi_internal_device_block(sdev);
+       scsi_internal_device_block(sdev, true);
 }
 
 static int
index 99bfc985e1903bcffd10762d52f1a72448aaed96..f11bd102d6d5d6b5a390762448002cd5b0f357d7 100644 (file)
@@ -188,8 +188,5 @@ static inline void scsi_dh_remove_device(struct scsi_device *sdev) { }
  */
 
 #define SCSI_DEVICE_BLOCK_MAX_TIMEOUT  600     /* units in seconds */
-extern int scsi_internal_device_block(struct scsi_device *sdev);
-extern int scsi_internal_device_unblock(struct scsi_device *sdev,
-                                       enum scsi_device_state new_state);
 
 #endif /* _SCSI_PRIV_H */
index d277e8620e3e39794584ac29dc55cc3ce476a03a..fcfeddc79331bbf32a71e296cf606513ae5b3d78 100644 (file)
@@ -1783,6 +1783,8 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
        unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
+       unsigned int sector_size = SCpnt->device->sector_size;
+       unsigned int resid;
        struct scsi_sense_hdr sshdr;
        struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
        struct request *req = SCpnt->request;
@@ -1813,6 +1815,21 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                        scsi_set_resid(SCpnt, blk_rq_bytes(req));
                }
                break;
+       default:
+               /*
+                * In case of bogus fw or device, we could end up having
+                * an unaligned partial completion. Check this here and force
+                * alignment.
+                */
+               resid = scsi_get_resid(SCpnt);
+               if (resid & (sector_size - 1)) {
+                       sd_printk(KERN_INFO, sdkp,
+                               "Unaligned partial completion (resid=%u, sector_sz=%u)\n",
+                               resid, sector_size);
+                       resid = min(scsi_bufflen(SCpnt),
+                                   round_up(resid, sector_size));
+                       scsi_set_resid(SCpnt, resid);
+               }
        }
 
        if (result) {
index 638e5f427c901fddee96a53328cd8cc76f1368be..016639d7fef176da5e54ddc5d4d32e110ea0656a 100644 (file)
@@ -400,8 +400,6 @@ MODULE_PARM_DESC(storvsc_vcpus_per_sub_channel, "Ratio of VCPUs to subchannels")
  */
 static int storvsc_timeout = 180;
 
-static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
-
 #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
 static struct scsi_transport_template *fc_transport_template;
 #endif
@@ -1383,6 +1381,22 @@ static int storvsc_do_io(struct hv_device *device,
        return ret;
 }
 
+static int storvsc_device_alloc(struct scsi_device *sdevice)
+{
+       /*
+        * Set blist flag to permit the reading of the VPD pages even when
+        * the target may claim SPC-2 compliance. MSFT targets currently
+        * claim SPC-2 compliance while they implement post SPC-2 features.
+        * With this flag we can correctly handle WRITE_SAME_16 issues.
+        *
+        * Hypervisor reports SCSI_UNKNOWN type for DVD ROM device but
+        * still supports REPORT LUN.
+        */
+       sdevice->sdev_bflags = BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES;
+
+       return 0;
+}
+
 static int storvsc_device_configure(struct scsi_device *sdevice)
 {
 
@@ -1395,14 +1409,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
 
        sdevice->no_write_same = 1;
 
-       /*
-        * Add blist flags to permit the reading of the VPD pages even when
-        * the target may claim SPC-2 compliance. MSFT targets currently
-        * claim SPC-2 compliance while they implement post SPC-2 features.
-        * With this patch we can correctly handle WRITE_SAME_16 issues.
-        */
-       sdevice->sdev_bflags |= msft_blist_flags;
-
        /*
         * If the host is WIN8 or WIN8 R2, claim conformance to SPC-3
         * if the device is a MSFT virtual device.  If the host is
@@ -1661,6 +1667,7 @@ static struct scsi_host_template scsi_driver = {
        .eh_host_reset_handler =        storvsc_host_reset_handler,
        .proc_name =            "storvsc_host",
        .eh_timed_out =         storvsc_eh_timed_out,
+       .slave_alloc =          storvsc_device_alloc,
        .slave_configure =      storvsc_device_configure,
        .cmd_per_lun =          255,
        .this_id =              -1,
index 318e4a1f76c92bab27954b5cc29a3d374c8eb6e7..54deeb754db5fccf7d918b604916b30d8defa8e5 100644 (file)
@@ -146,7 +146,7 @@ enum attr_idn {
 /* Descriptor idn for Query requests */
 enum desc_idn {
        QUERY_DESC_IDN_DEVICE           = 0x0,
-       QUERY_DESC_IDN_CONFIGURAION     = 0x1,
+       QUERY_DESC_IDN_CONFIGURATION    = 0x1,
        QUERY_DESC_IDN_UNIT             = 0x2,
        QUERY_DESC_IDN_RFU_0            = 0x3,
        QUERY_DESC_IDN_INTERCONNECT     = 0x4,
@@ -162,19 +162,13 @@ enum desc_header_offset {
        QUERY_DESC_DESC_TYPE_OFFSET     = 0x01,
 };
 
-enum ufs_desc_max_size {
-       QUERY_DESC_DEVICE_MAX_SIZE              = 0x40,
-       QUERY_DESC_CONFIGURAION_MAX_SIZE        = 0x90,
-       QUERY_DESC_UNIT_MAX_SIZE                = 0x23,
-       QUERY_DESC_INTERCONNECT_MAX_SIZE        = 0x06,
-       /*
-        * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes
-        * of descriptor header.
-        */
-       QUERY_DESC_STRING_MAX_SIZE              = 0xFE,
-       QUERY_DESC_GEOMETRY_MAX_SIZE            = 0x44,
-       QUERY_DESC_POWER_MAX_SIZE               = 0x62,
-       QUERY_DESC_RFU_MAX_SIZE                 = 0x00,
+enum ufs_desc_def_size {
+       QUERY_DESC_DEVICE_DEF_SIZE              = 0x40,
+       QUERY_DESC_CONFIGURATION_DEF_SIZE       = 0x90,
+       QUERY_DESC_UNIT_DEF_SIZE                = 0x23,
+       QUERY_DESC_INTERCONNECT_DEF_SIZE        = 0x06,
+       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x44,
+       QUERY_DESC_POWER_DEF_SIZE               = 0x62,
 };
 
 /* Unit descriptor parameters offsets in bytes*/
index dc6efbd1be8ef344bb994589054c24843e442230..e8c26e6e623726fe15f8e40ddafa089d68869c33 100644 (file)
 #define ufshcd_hex_dump(prefix_str, buf, len) \
 print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false)
 
-static u32 ufs_query_desc_max_size[] = {
-       QUERY_DESC_DEVICE_MAX_SIZE,
-       QUERY_DESC_CONFIGURAION_MAX_SIZE,
-       QUERY_DESC_UNIT_MAX_SIZE,
-       QUERY_DESC_RFU_MAX_SIZE,
-       QUERY_DESC_INTERCONNECT_MAX_SIZE,
-       QUERY_DESC_STRING_MAX_SIZE,
-       QUERY_DESC_RFU_MAX_SIZE,
-       QUERY_DESC_GEOMETRY_MAX_SIZE,
-       QUERY_DESC_POWER_MAX_SIZE,
-       QUERY_DESC_RFU_MAX_SIZE,
-};
-
 enum {
        UFSHCD_MAX_CHANNEL      = 0,
        UFSHCD_MAX_ID           = 1,
@@ -2857,7 +2844,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
                goto out;
        }
 
-       if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) {
+       if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) {
                dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n",
                                __func__, *buf_len);
                err = -EINVAL;
@@ -2937,6 +2924,92 @@ static int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
        return err;
 }
 
+/**
+ * ufshcd_read_desc_length - read the specified descriptor length from header
+ * @hba: Pointer to adapter instance
+ * @desc_id: descriptor idn value
+ * @desc_index: descriptor index
+ * @desc_length: pointer to variable to read the length of descriptor
+ *
+ * Return 0 in case of success, non-zero otherwise
+ */
+static int ufshcd_read_desc_length(struct ufs_hba *hba,
+       enum desc_idn desc_id,
+       int desc_index,
+       int *desc_length)
+{
+       int ret;
+       u8 header[QUERY_DESC_HDR_SIZE];
+       int header_len = QUERY_DESC_HDR_SIZE;
+
+       if (desc_id >= QUERY_DESC_IDN_MAX)
+               return -EINVAL;
+
+       ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
+                                       desc_id, desc_index, 0, header,
+                                       &header_len);
+
+       if (ret) {
+               dev_err(hba->dev, "%s: Failed to get descriptor header id %d",
+                       __func__, desc_id);
+               return ret;
+       } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) {
+               dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch",
+                       __func__, header[QUERY_DESC_DESC_TYPE_OFFSET],
+                       desc_id);
+               ret = -EINVAL;
+       }
+
+       *desc_length = header[QUERY_DESC_LENGTH_OFFSET];
+       return ret;
+
+}
+
+/**
+ * ufshcd_map_desc_id_to_length - map descriptor IDN to its length
+ * @hba: Pointer to adapter instance
+ * @desc_id: descriptor idn value
+ * @desc_len: mapped desc length (out)
+ *
+ * Return 0 in case of success, non-zero otherwise
+ */
+int ufshcd_map_desc_id_to_length(struct ufs_hba *hba,
+       enum desc_idn desc_id, int *desc_len)
+{
+       switch (desc_id) {
+       case QUERY_DESC_IDN_DEVICE:
+               *desc_len = hba->desc_size.dev_desc;
+               break;
+       case QUERY_DESC_IDN_POWER:
+               *desc_len = hba->desc_size.pwr_desc;
+               break;
+       case QUERY_DESC_IDN_GEOMETRY:
+               *desc_len = hba->desc_size.geom_desc;
+               break;
+       case QUERY_DESC_IDN_CONFIGURATION:
+               *desc_len = hba->desc_size.conf_desc;
+               break;
+       case QUERY_DESC_IDN_UNIT:
+               *desc_len = hba->desc_size.unit_desc;
+               break;
+       case QUERY_DESC_IDN_INTERCONNECT:
+               *desc_len = hba->desc_size.interc_desc;
+               break;
+       case QUERY_DESC_IDN_STRING:
+               *desc_len = QUERY_DESC_MAX_SIZE;
+               break;
+       case QUERY_DESC_IDN_RFU_0:
+       case QUERY_DESC_IDN_RFU_1:
+               *desc_len = 0;
+               break;
+       default:
+               *desc_len = 0;
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);
+
 /**
  * ufshcd_read_desc_param - read the specified descriptor parameter
  * @hba: Pointer to adapter instance
@@ -2951,42 +3024,49 @@ static int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
 static int ufshcd_read_desc_param(struct ufs_hba *hba,
                                  enum desc_idn desc_id,
                                  int desc_index,
-                                 u32 param_offset,
+                                 u8 param_offset,
                                  u8 *param_read_buf,
-                                 u32 param_size)
+                                 u8 param_size)
 {
        int ret;
        u8 *desc_buf;
-       u32 buff_len;
+       int buff_len;
        bool is_kmalloc = true;
 
-       /* safety checks */
-       if (desc_id >= QUERY_DESC_IDN_MAX)
+       /* Safety check */
+       if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
                return -EINVAL;
 
-       buff_len = ufs_query_desc_max_size[desc_id];
-       if ((param_offset + param_size) > buff_len)
-               return -EINVAL;
+       /* Get the max length of descriptor from structure filled up at probe
+        * time.
+        */
+       ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
 
-       if (!param_offset && (param_size == buff_len)) {
-               /* memory space already available to hold full descriptor */
-               desc_buf = param_read_buf;
-               is_kmalloc = false;
-       } else {
-               /* allocate memory to hold full descriptor */
+       /* Sanity checks */
+       if (ret || !buff_len) {
+               dev_err(hba->dev, "%s: Failed to get full descriptor length",
+                       __func__);
+               return ret;
+       }
+
+       /* Check whether we need temp memory */
+       if (param_offset != 0 || param_size < buff_len) {
                desc_buf = kmalloc(buff_len, GFP_KERNEL);
                if (!desc_buf)
                        return -ENOMEM;
+       } else {
+               desc_buf = param_read_buf;
+               is_kmalloc = false;
        }
 
+       /* Request for full descriptor */
        ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
-                                       desc_id, desc_index, 0, desc_buf,
-                                       &buff_len);
+                                       desc_id, desc_index, 0,
+                                       desc_buf, &buff_len);
 
        if (ret) {
                dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d",
                        __func__, desc_id, desc_index, param_offset, ret);
-
                goto out;
        }
 
@@ -2998,25 +3078,9 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba,
                goto out;
        }
 
-       /*
-        * While reading variable size descriptors (like string descriptor),
-        * some UFS devices may report the "LENGTH" (field in "Transaction
-        * Specific fields" of Query Response UPIU) same as what was requested
-        * in Query Request UPIU instead of reporting the actual size of the
-        * variable size descriptor.
-        * Although it's safe to ignore the "LENGTH" field for variable size
-        * descriptors as we can always derive the length of the descriptor from
-        * the descriptor header fields. Hence this change impose the length
-        * match check only for fixed size descriptors (for which we always
-        * request the correct size as part of Query Request UPIU).
-        */
-       if ((desc_id != QUERY_DESC_IDN_STRING) &&
-           (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) {
-               dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d",
-                       __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]);
-               ret = -EINVAL;
-               goto out;
-       }
+       /* Check wherher we will not copy more data, than available */
+       if (is_kmalloc && param_size > buff_len)
+               param_size = buff_len;
 
        if (is_kmalloc)
                memcpy(param_read_buf, &desc_buf[param_offset], param_size);
@@ -5919,8 +5983,8 @@ static int ufshcd_set_icc_levels_attr(struct ufs_hba *hba, u32 icc_level)
 static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 {
        int ret;
-       int buff_len = QUERY_DESC_POWER_MAX_SIZE;
-       u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE];
+       int buff_len = hba->desc_size.pwr_desc;
+       u8 desc_buf[hba->desc_size.pwr_desc];
 
        ret = ufshcd_read_power_desc(hba, desc_buf, buff_len);
        if (ret) {
@@ -6017,11 +6081,10 @@ static int ufs_get_device_desc(struct ufs_hba *hba,
 {
        int err;
        u8 model_index;
-       u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1] = {0};
-       u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
+       u8 str_desc_buf[QUERY_DESC_MAX_SIZE + 1] = {0};
+       u8 desc_buf[hba->desc_size.dev_desc];
 
-       err = ufshcd_read_device_desc(hba, desc_buf,
-                                       QUERY_DESC_DEVICE_MAX_SIZE);
+       err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc);
        if (err) {
                dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n",
                        __func__, err);
@@ -6038,14 +6101,14 @@ static int ufs_get_device_desc(struct ufs_hba *hba,
        model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
 
        err = ufshcd_read_string_desc(hba, model_index, str_desc_buf,
-                                       QUERY_DESC_STRING_MAX_SIZE, ASCII_STD);
+                               QUERY_DESC_MAX_SIZE, ASCII_STD);
        if (err) {
                dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n",
                        __func__, err);
                goto out;
        }
 
-       str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0';
+       str_desc_buf[QUERY_DESC_MAX_SIZE] = '\0';
        strlcpy(dev_desc->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
                min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET],
                      MAX_MODEL_LEN));
@@ -6251,6 +6314,51 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba)
        hba->req_abort_count = 0;
 }
 
+static void ufshcd_init_desc_sizes(struct ufs_hba *hba)
+{
+       int err;
+
+       err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0,
+               &hba->desc_size.dev_desc);
+       if (err)
+               hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE;
+
+       err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0,
+               &hba->desc_size.pwr_desc);
+       if (err)
+               hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE;
+
+       err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0,
+               &hba->desc_size.interc_desc);
+       if (err)
+               hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE;
+
+       err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0,
+               &hba->desc_size.conf_desc);
+       if (err)
+               hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE;
+
+       err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0,
+               &hba->desc_size.unit_desc);
+       if (err)
+               hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE;
+
+       err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0,
+               &hba->desc_size.geom_desc);
+       if (err)
+               hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
+}
+
+static void ufshcd_def_desc_sizes(struct ufs_hba *hba)
+{
+       hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE;
+       hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE;
+       hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE;
+       hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE;
+       hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE;
+       hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
+}
+
 /**
  * ufshcd_probe_hba - probe hba to detect device and initialize
  * @hba: per-adapter instance
@@ -6285,6 +6393,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
        if (ret)
                goto out;
 
+       /* Init check for device descriptor sizes */
+       ufshcd_init_desc_sizes(hba);
+
        ret = ufs_get_device_desc(hba, &card);
        if (ret) {
                dev_err(hba->dev, "%s: Failed getting device info. err = %d\n",
@@ -6320,6 +6431,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 
        /* set the state as operational after switching to desired gear */
        hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+
        /*
         * If we are in error handling context or in power management callbacks
         * context, no need to scan the host
@@ -7530,7 +7642,7 @@ static inline ssize_t ufshcd_pm_lvl_store(struct device *dev,
        if (kstrtoul(buf, 0, &value))
                return -EINVAL;
 
-       if ((value < UFS_PM_LVL_0) || (value >= UFS_PM_LVL_MAX))
+       if (value >= UFS_PM_LVL_MAX)
                return -EINVAL;
 
        spin_lock_irqsave(hba->host->host_lock, flags);
@@ -7774,6 +7886,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
        hba->mmio_base = mmio_base;
        hba->irq = irq;
 
+       /* Set descriptor lengths to specification defaults */
+       ufshcd_def_desc_sizes(hba);
+
        err = ufshcd_hba_init(hba);
        if (err)
                goto out_error;
index 7630600217a2ef91e7d3629e5a4d2a0716c24c2a..cdc8bd05f7dfcf7189a4a616bb90c2ea3a8e2ece 100644 (file)
@@ -220,6 +220,15 @@ struct ufs_dev_cmd {
        struct ufs_query query;
 };
 
+struct ufs_desc_size {
+       int dev_desc;
+       int pwr_desc;
+       int geom_desc;
+       int interc_desc;
+       int unit_desc;
+       int conf_desc;
+};
+
 /**
  * struct ufs_clk_info - UFS clock related info
  * @list: list headed by hba->clk_list_head
@@ -483,6 +492,7 @@ struct ufs_stats {
  * @clk_list_head: UFS host controller clocks list node head
  * @pwr_info: holds current power mode
  * @max_pwr_info: keeps the device max valid pwm
+ * @desc_size: descriptor sizes reported by device
  * @urgent_bkops_lvl: keeps track of urgent bkops level for device
  * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
  *  device is known or not.
@@ -666,6 +676,7 @@ struct ufs_hba {
        bool is_urgent_bkops_lvl_checked;
 
        struct rw_semaphore clk_scaling_lock;
+       struct ufs_desc_size desc_size;
 };
 
 /* Returns true if clocks can be gated. Otherwise false */
@@ -832,6 +843,10 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
        enum flag_idn idn, bool *flag_res);
 int ufshcd_hold(struct ufs_hba *hba, bool async);
 void ufshcd_release(struct ufs_hba *hba);
+
+int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
+       int *desc_length);
+
 u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
 
 /* Wrapper functions for safely calling variant operations */
index ef474a7487449b4c1d51f82643988eb08fc1ed86..c374e3b5c678d215bfa9e7ed33e2d033e5d4bfb3 100644 (file)
@@ -1487,7 +1487,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                irq_flag &= ~PCI_IRQ_MSI;
 
        error = pci_alloc_irq_vectors(adapter->dev, 1, 1, irq_flag);
-       if (error)
+       if (error < 0)
                goto out_reset_adapter;
 
        adapter->use_req_threshold = pvscsi_setup_req_threshold(adapter, true);
index b7b87ecefcdfc712b74a79298594cdaa94ab68bc..9fca8d225ee092e92e1fb71a7a6faff5ee1a831c 100644 (file)
@@ -532,7 +532,7 @@ lnet_sock_accept(struct socket **newsockp, struct socket *sock)
 
        newsock->ops = sock->ops;
 
-       rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
+       rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
        if (rc == -EAGAIN) {
                /* Nothing ready, so wait for activity */
                init_waitqueue_entry(&wait, current);
@@ -540,7 +540,7 @@ lnet_sock_accept(struct socket **newsockp, struct socket *sock)
                set_current_state(TASK_INTERRUPTIBLE);
                schedule();
                remove_wait_queue(sk_sleep(sock->sk), &wait);
-               rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
+               rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
        }
 
        if (rc)
index f5e330099bfca713f4cb12bd2dc77826fdad1b3b..fd7c16a7ca6e06ad53e6d6df54ab739550ae4a4a 100644 (file)
@@ -43,7 +43,7 @@
 #include "target_core_ua.h"
 
 static sense_reason_t core_alua_check_transition(int state, int valid,
-                                                int *primary);
+                                                int *primary, int explicit);
 static int core_alua_set_tg_pt_secondary_state(
                struct se_lun *lun, int explicit, int offline);
 
@@ -335,8 +335,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
                 * the state is a primary or secondary target port asymmetric
                 * access state.
                 */
-               rc = core_alua_check_transition(alua_access_state,
-                                               valid_states, &primary);
+               rc = core_alua_check_transition(alua_access_state, valid_states,
+                                               &primary, 1);
                if (rc) {
                        /*
                         * If the SET TARGET PORT GROUPS attempts to establish
@@ -691,7 +691,7 @@ target_alua_state_check(struct se_cmd *cmd)
 
        if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
                return 0;
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA)
                return 0;
 
        /*
@@ -762,7 +762,7 @@ target_alua_state_check(struct se_cmd *cmd)
  * Check implicit and explicit ALUA state change request.
  */
 static sense_reason_t
-core_alua_check_transition(int state, int valid, int *primary)
+core_alua_check_transition(int state, int valid, int *primary, int explicit)
 {
        /*
         * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
@@ -804,11 +804,14 @@ core_alua_check_transition(int state, int valid, int *primary)
                *primary = 0;
                break;
        case ALUA_ACCESS_STATE_TRANSITION:
-               /*
-                * Transitioning is set internally, and
-                * cannot be selected manually.
-                */
-               goto not_supported;
+               if (!(valid & ALUA_T_SUP) || explicit)
+                       /*
+                        * Transitioning is set internally and by tcmu daemon,
+                        * and cannot be selected through a STPG.
+                        */
+                       goto not_supported;
+               *primary = 0;
+               break;
        default:
                pr_err("Unknown ALUA access state: 0x%02x\n", state);
                return TCM_INVALID_PARAMETER_LIST;
@@ -1013,7 +1016,7 @@ static void core_alua_queue_state_change_ua(struct t10_alua_tg_pt_gp *tg_pt_gp)
 static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
 {
        struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work,
-               struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work);
+               struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work);
        struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
        bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status ==
                         ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG);
@@ -1070,32 +1073,19 @@ static int core_alua_do_transition_tg_pt(
        if (atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == new_state)
                return 0;
 
-       if (new_state == ALUA_ACCESS_STATE_TRANSITION)
+       if (explicit && new_state == ALUA_ACCESS_STATE_TRANSITION)
                return -EAGAIN;
 
        /*
         * Flush any pending transitions
         */
-       if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs &&
-           atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) ==
-           ALUA_ACCESS_STATE_TRANSITION) {
-               /* Just in case */
-               tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
-               tg_pt_gp->tg_pt_gp_transition_complete = &wait;
-               flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work);
-               wait_for_completion(&wait);
-               tg_pt_gp->tg_pt_gp_transition_complete = NULL;
-               return 0;
-       }
+       if (!explicit)
+               flush_work(&tg_pt_gp->tg_pt_gp_transition_work);
 
        /*
         * Save the old primary ALUA access state, and set the current state
         * to ALUA_ACCESS_STATE_TRANSITION.
         */
-       tg_pt_gp->tg_pt_gp_alua_previous_state =
-               atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
-       tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
-
        atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
                        ALUA_ACCESS_STATE_TRANSITION);
        tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
@@ -1104,6 +1094,13 @@ static int core_alua_do_transition_tg_pt(
 
        core_alua_queue_state_change_ua(tg_pt_gp);
 
+       if (new_state == ALUA_ACCESS_STATE_TRANSITION)
+               return 0;
+
+       tg_pt_gp->tg_pt_gp_alua_previous_state =
+               atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
+       tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
+
        /*
         * Check for the optional ALUA primary state transition delay
         */
@@ -1117,17 +1114,9 @@ static int core_alua_do_transition_tg_pt(
        atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
        spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
-       if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) {
-               unsigned long transition_tmo;
-
-               transition_tmo = tg_pt_gp->tg_pt_gp_implicit_trans_secs * HZ;
-               queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
-                                  &tg_pt_gp->tg_pt_gp_transition_work,
-                                  transition_tmo);
-       } else {
+       schedule_work(&tg_pt_gp->tg_pt_gp_transition_work);
+       if (explicit) {
                tg_pt_gp->tg_pt_gp_transition_complete = &wait;
-               queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
-                                  &tg_pt_gp->tg_pt_gp_transition_work, 0);
                wait_for_completion(&wait);
                tg_pt_gp->tg_pt_gp_transition_complete = NULL;
        }
@@ -1149,8 +1138,12 @@ int core_alua_do_port_transition(
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        int primary, valid_states, rc = 0;
 
+       if (l_dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA)
+               return -ENODEV;
+
        valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
-       if (core_alua_check_transition(new_state, valid_states, &primary) != 0)
+       if (core_alua_check_transition(new_state, valid_states, &primary,
+                                      explicit) != 0)
                return -EINVAL;
 
        local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem;
@@ -1695,8 +1688,8 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
        mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex);
        spin_lock_init(&tg_pt_gp->tg_pt_gp_lock);
        atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0);
-       INIT_DELAYED_WORK(&tg_pt_gp->tg_pt_gp_transition_work,
-                         core_alua_do_transition_tg_pt_work);
+       INIT_WORK(&tg_pt_gp->tg_pt_gp_transition_work,
+                 core_alua_do_transition_tg_pt_work);
        tg_pt_gp->tg_pt_gp_dev = dev;
        atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
                ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED);
@@ -1804,7 +1797,7 @@ void core_alua_free_tg_pt_gp(
        dev->t10_alua.alua_tg_pt_gps_counter--;
        spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
-       flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work);
+       flush_work(&tg_pt_gp->tg_pt_gp_transition_work);
 
        /*
         * Allow a struct t10_alua_tg_pt_gp_member * referenced by
@@ -1973,7 +1966,7 @@ ssize_t core_alua_store_tg_pt_gp_info(
        unsigned char buf[TG_PT_GROUP_NAME_BUF];
        int move = 0;
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH ||
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ||
            (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
                return -ENODEV;
 
@@ -2230,7 +2223,7 @@ ssize_t core_alua_store_offline_bit(
        unsigned long tmp;
        int ret;
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH ||
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA ||
            (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
                return -ENODEV;
 
@@ -2316,7 +2309,8 @@ ssize_t core_alua_store_secondary_write_metadata(
 
 int core_setup_alua(struct se_device *dev)
 {
-       if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) &&
+       if (!(dev->transport->transport_flags &
+            TRANSPORT_FLAG_PASSTHROUGH_ALUA) &&
            !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
                struct t10_alua_lu_gp_member *lu_gp_mem;
 
index 54b36c9835be3ae2127cb1f447321eba73b824ac..38b5025e4c7a877f9e5c0bcfa6995262b6330e32 100644 (file)
@@ -421,6 +421,10 @@ static int target_fabric_tf_ops_check(const struct target_core_fabric_ops *tfo)
                pr_err("Missing tfo->aborted_task()\n");
                return -EINVAL;
        }
+       if (!tfo->check_stop_free) {
+               pr_err("Missing tfo->check_stop_free()\n");
+               return -EINVAL;
+       }
        /*
         * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn()
         * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in
index a8f8e53f2f574852de573a08a86ad1c25b4cf332..94cda7991e80abbffb32941c8d8f5cfcbd262e3f 100644 (file)
@@ -154,7 +154,7 @@ static void pscsi_tape_read_blocksize(struct se_device *dev,
 
        buf = kzalloc(12, GFP_KERNEL);
        if (!buf)
-               return;
+               goto out_free;
 
        memset(cdb, 0, MAX_COMMAND_SIZE);
        cdb[0] = MODE_SENSE;
@@ -169,9 +169,10 @@ static void pscsi_tape_read_blocksize(struct se_device *dev,
         * If MODE_SENSE still returns zero, set the default value to 1024.
         */
        sdev->sector_size = (buf[9] << 16) | (buf[10] << 8) | (buf[11]);
+out_free:
        if (!sdev->sector_size)
                sdev->sector_size = 1024;
-out_free:
+
        kfree(buf);
 }
 
@@ -314,9 +315,10 @@ static int pscsi_add_device_to_list(struct se_device *dev,
                                sd->lun, sd->queue_depth);
        }
 
-       dev->dev_attrib.hw_block_size = sd->sector_size;
+       dev->dev_attrib.hw_block_size =
+               min_not_zero((int)sd->sector_size, 512);
        dev->dev_attrib.hw_max_sectors =
-               min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q));
+               min_not_zero(sd->host->max_sectors, queue_max_hw_sectors(q));
        dev->dev_attrib.hw_queue_depth = sd->queue_depth;
 
        /*
@@ -339,8 +341,10 @@ static int pscsi_add_device_to_list(struct se_device *dev,
        /*
         * For TYPE_TAPE, attempt to determine blocksize with MODE_SENSE.
         */
-       if (sd->type == TYPE_TAPE)
+       if (sd->type == TYPE_TAPE) {
                pscsi_tape_read_blocksize(dev, sd);
+               dev->dev_attrib.hw_block_size = sd->sector_size;
+       }
        return 0;
 }
 
@@ -406,7 +410,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
 /*
  * Called with struct Scsi_Host->host_lock called.
  */
-static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd)
+static int pscsi_create_type_nondisk(struct se_device *dev, struct scsi_device *sd)
        __releases(sh->host_lock)
 {
        struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
@@ -433,28 +437,6 @@ static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd)
        return 0;
 }
 
-/*
- * Called with struct Scsi_Host->host_lock called.
- */
-static int pscsi_create_type_other(struct se_device *dev,
-               struct scsi_device *sd)
-       __releases(sh->host_lock)
-{
-       struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
-       struct Scsi_Host *sh = sd->host;
-       int ret;
-
-       spin_unlock_irq(sh->host_lock);
-       ret = pscsi_add_device_to_list(dev, sd);
-       if (ret)
-               return ret;
-
-       pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%llu\n",
-               phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
-               sd->channel, sd->id, sd->lun);
-       return 0;
-}
-
 static int pscsi_configure_device(struct se_device *dev)
 {
        struct se_hba *hba = dev->se_hba;
@@ -542,11 +524,8 @@ static int pscsi_configure_device(struct se_device *dev)
                case TYPE_DISK:
                        ret = pscsi_create_type_disk(dev, sd);
                        break;
-               case TYPE_ROM:
-                       ret = pscsi_create_type_rom(dev, sd);
-                       break;
                default:
-                       ret = pscsi_create_type_other(dev, sd);
+                       ret = pscsi_create_type_nondisk(dev, sd);
                        break;
                }
 
@@ -611,8 +590,7 @@ static void pscsi_free_device(struct se_device *dev)
                else if (pdv->pdv_lld_host)
                        scsi_host_put(pdv->pdv_lld_host);
 
-               if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
-                       scsi_device_put(sd);
+               scsi_device_put(sd);
 
                pdv->pdv_sd = NULL;
        }
@@ -1064,7 +1042,6 @@ static sector_t pscsi_get_blocks(struct se_device *dev)
        if (pdv->pdv_bd && pdv->pdv_bd->bd_part)
                return pdv->pdv_bd->bd_part->nr_sects;
 
-       dump_stack();
        return 0;
 }
 
@@ -1103,7 +1080,8 @@ static void pscsi_req_done(struct request *req, int uptodate)
 static const struct target_backend_ops pscsi_ops = {
        .name                   = "pscsi",
        .owner                  = THIS_MODULE,
-       .transport_flags        = TRANSPORT_FLAG_PASSTHROUGH,
+       .transport_flags        = TRANSPORT_FLAG_PASSTHROUGH |
+                                 TRANSPORT_FLAG_PASSTHROUGH_ALUA,
        .attach_hba             = pscsi_attach_hba,
        .detach_hba             = pscsi_detach_hba,
        .pmode_enable_hba       = pscsi_pmode_enable_hba,
index 68d8aef7ab78d4084b57e6fd0fa0b0afce7251df..c194063f169b13ce44bf014894960693530e25d7 100644 (file)
@@ -1105,9 +1105,15 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
                        return ret;
                break;
        case VERIFY:
+       case VERIFY_16:
                size = 0;
-               sectors = transport_get_sectors_10(cdb);
-               cmd->t_task_lba = transport_lba_32(cdb);
+               if (cdb[0] == VERIFY) {
+                       sectors = transport_get_sectors_10(cdb);
+                       cmd->t_task_lba = transport_lba_32(cdb);
+               } else {
+                       sectors = transport_get_sectors_16(cdb);
+                       cmd->t_task_lba = transport_lba_64(cdb);
+               }
                cmd->execute_cmd = sbc_emulate_noop;
                goto check_lba;
        case REZERO_UNIT:
index c0dbfa0165750523e552b93fdbb0c64c94cdab2d..6fb191914f458f7889508652e19b860355387491 100644 (file)
@@ -602,7 +602,8 @@ int core_tpg_add_lun(
        if (ret)
                goto out_kill_ref;
 
-       if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) &&
+       if (!(dev->transport->transport_flags &
+            TRANSPORT_FLAG_PASSTHROUGH_ALUA) &&
            !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
                target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp);
 
index 434d9d693989179f72abca120e01155d664d0c87..b1a3cdb29468cf84e7eb48d6c8c41934c0b5b4cb 100644 (file)
@@ -636,8 +636,7 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
         * Fabric modules are expected to return '1' here if the se_cmd being
         * passed is released at this point, or zero if not being released.
         */
-       return cmd->se_tfo->check_stop_free ? cmd->se_tfo->check_stop_free(cmd)
-               : 0;
+       return cmd->se_tfo->check_stop_free(cmd);
 }
 
 static void transport_lun_remove_cmd(struct se_cmd *cmd)
index c3adefe95e50f7f7054e272e15fc5e37663d11c9..c6874c38a10bc45e86beae58ddfed175664d51cf 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/stringify.h>
 #include <linux/bitops.h>
 #include <linux/highmem.h>
+#include <linux/configfs.h>
 #include <net/genetlink.h>
 #include <scsi/scsi_common.h>
 #include <scsi/scsi_proto.h>
@@ -112,6 +113,7 @@ struct tcmu_dev {
        spinlock_t commands_lock;
 
        struct timer_list timeout;
+       unsigned int cmd_time_out;
 
        char dev_config[TCMU_CONFIG_LEN];
 };
@@ -172,7 +174,9 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
 
        tcmu_cmd->se_cmd = se_cmd;
        tcmu_cmd->tcmu_dev = udev;
-       tcmu_cmd->deadline = jiffies + msecs_to_jiffies(TCMU_TIME_OUT);
+       if (udev->cmd_time_out)
+               tcmu_cmd->deadline = jiffies +
+                                       msecs_to_jiffies(udev->cmd_time_out);
 
        idr_preload(GFP_KERNEL);
        spin_lock_irq(&udev->commands_lock);
@@ -451,7 +455,11 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 
                pr_debug("sleeping for ring space\n");
                spin_unlock_irq(&udev->cmdr_lock);
-               ret = schedule_timeout(msecs_to_jiffies(TCMU_TIME_OUT));
+               if (udev->cmd_time_out)
+                       ret = schedule_timeout(
+                                       msecs_to_jiffies(udev->cmd_time_out));
+               else
+                       ret = schedule_timeout(msecs_to_jiffies(TCMU_TIME_OUT));
                finish_wait(&udev->wait_cmdr, &__wait);
                if (!ret) {
                        pr_warn("tcmu: command timed out\n");
@@ -526,8 +534,9 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
        /* TODO: only if FLUSH and FUA? */
        uio_event_notify(&udev->uio_info);
 
-       mod_timer(&udev->timeout,
-               round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT)));
+       if (udev->cmd_time_out)
+               mod_timer(&udev->timeout, round_jiffies_up(jiffies +
+                         msecs_to_jiffies(udev->cmd_time_out)));
 
        return TCM_NO_SENSE;
 }
@@ -742,6 +751,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
        }
 
        udev->hba = hba;
+       udev->cmd_time_out = TCMU_TIME_OUT;
 
        init_waitqueue_head(&udev->wait_cmdr);
        spin_lock_init(&udev->cmdr_lock);
@@ -960,7 +970,8 @@ static int tcmu_configure_device(struct se_device *dev)
        if (dev->dev_attrib.hw_block_size == 0)
                dev->dev_attrib.hw_block_size = 512;
        /* Other attributes can be configured in userspace */
-       dev->dev_attrib.hw_max_sectors = 128;
+       if (!dev->dev_attrib.hw_max_sectors)
+               dev->dev_attrib.hw_max_sectors = 128;
        dev->dev_attrib.hw_queue_depth = 128;
 
        ret = tcmu_netlink_event(TCMU_CMD_ADDED_DEVICE, udev->uio_info.name,
@@ -997,6 +1008,11 @@ static void tcmu_dev_call_rcu(struct rcu_head *p)
        kfree(udev);
 }
 
+static bool tcmu_dev_configured(struct tcmu_dev *udev)
+{
+       return udev->uio_info.uio_dev ? true : false;
+}
+
 static void tcmu_free_device(struct se_device *dev)
 {
        struct tcmu_dev *udev = TCMU_DEV(dev);
@@ -1018,8 +1034,7 @@ static void tcmu_free_device(struct se_device *dev)
        spin_unlock_irq(&udev->commands_lock);
        WARN_ON(!all_expired);
 
-       /* Device was configured */
-       if (udev->uio_info.uio_dev) {
+       if (tcmu_dev_configured(udev)) {
                tcmu_netlink_event(TCMU_CMD_REMOVED_DEVICE, udev->uio_info.name,
                                   udev->uio_info.uio_dev->minor);
 
@@ -1031,16 +1046,42 @@ static void tcmu_free_device(struct se_device *dev)
 }
 
 enum {
-       Opt_dev_config, Opt_dev_size, Opt_hw_block_size, Opt_err,
+       Opt_dev_config, Opt_dev_size, Opt_hw_block_size, Opt_hw_max_sectors,
+       Opt_err,
 };
 
 static match_table_t tokens = {
        {Opt_dev_config, "dev_config=%s"},
        {Opt_dev_size, "dev_size=%u"},
        {Opt_hw_block_size, "hw_block_size=%u"},
+       {Opt_hw_max_sectors, "hw_max_sectors=%u"},
        {Opt_err, NULL}
 };
 
+static int tcmu_set_dev_attrib(substring_t *arg, u32 *dev_attrib)
+{
+       unsigned long tmp_ul;
+       char *arg_p;
+       int ret;
+
+       arg_p = match_strdup(arg);
+       if (!arg_p)
+               return -ENOMEM;
+
+       ret = kstrtoul(arg_p, 0, &tmp_ul);
+       kfree(arg_p);
+       if (ret < 0) {
+               pr_err("kstrtoul() failed for dev attrib\n");
+               return ret;
+       }
+       if (!tmp_ul) {
+               pr_err("dev attrib must be nonzero\n");
+               return -EINVAL;
+       }
+       *dev_attrib = tmp_ul;
+       return 0;
+}
+
 static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev,
                const char *page, ssize_t count)
 {
@@ -1048,7 +1089,6 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev,
        char *orig, *ptr, *opts, *arg_p;
        substring_t args[MAX_OPT_ARGS];
        int ret = 0, token;
-       unsigned long tmp_ul;
 
        opts = kstrdup(page, GFP_KERNEL);
        if (!opts)
@@ -1082,26 +1122,19 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev,
                                pr_err("kstrtoul() failed for dev_size=\n");
                        break;
                case Opt_hw_block_size:
-                       arg_p = match_strdup(&args[0]);
-                       if (!arg_p) {
-                               ret = -ENOMEM;
-                               break;
-                       }
-                       ret = kstrtoul(arg_p, 0, &tmp_ul);
-                       kfree(arg_p);
-                       if (ret < 0) {
-                               pr_err("kstrtoul() failed for hw_block_size=\n");
-                               break;
-                       }
-                       if (!tmp_ul) {
-                               pr_err("hw_block_size must be nonzero\n");
-                               break;
-                       }
-                       dev->dev_attrib.hw_block_size = tmp_ul;
+                       ret = tcmu_set_dev_attrib(&args[0],
+                                       &(dev->dev_attrib.hw_block_size));
+                       break;
+               case Opt_hw_max_sectors:
+                       ret = tcmu_set_dev_attrib(&args[0],
+                                       &(dev->dev_attrib.hw_max_sectors));
                        break;
                default:
                        break;
                }
+
+               if (ret)
+                       break;
        }
 
        kfree(orig);
@@ -1134,7 +1167,48 @@ tcmu_parse_cdb(struct se_cmd *cmd)
        return passthrough_parse_cdb(cmd, tcmu_queue_cmd);
 }
 
-static const struct target_backend_ops tcmu_ops = {
+static ssize_t tcmu_cmd_time_out_show(struct config_item *item, char *page)
+{
+       struct se_dev_attrib *da = container_of(to_config_group(item),
+                                       struct se_dev_attrib, da_group);
+       struct tcmu_dev *udev = container_of(da->da_dev,
+                                       struct tcmu_dev, se_dev);
+
+       return snprintf(page, PAGE_SIZE, "%lu\n", udev->cmd_time_out / MSEC_PER_SEC);
+}
+
+static ssize_t tcmu_cmd_time_out_store(struct config_item *item, const char *page,
+                                      size_t count)
+{
+       struct se_dev_attrib *da = container_of(to_config_group(item),
+                                       struct se_dev_attrib, da_group);
+       struct tcmu_dev *udev = container_of(da->da_dev,
+                                       struct tcmu_dev, se_dev);
+       u32 val;
+       int ret;
+
+       if (da->da_dev->export_count) {
+               pr_err("Unable to set tcmu cmd_time_out while exports exist\n");
+               return -EINVAL;
+       }
+
+       ret = kstrtou32(page, 0, &val);
+       if (ret < 0)
+               return ret;
+
+       if (!val) {
+               pr_err("Illegal value for cmd_time_out\n");
+               return -EINVAL;
+       }
+
+       udev->cmd_time_out = val * MSEC_PER_SEC;
+       return count;
+}
+CONFIGFS_ATTR(tcmu_, cmd_time_out);
+
+static struct configfs_attribute **tcmu_attrs;
+
+static struct target_backend_ops tcmu_ops = {
        .name                   = "user",
        .owner                  = THIS_MODULE,
        .transport_flags        = TRANSPORT_FLAG_PASSTHROUGH,
@@ -1148,12 +1222,12 @@ static const struct target_backend_ops tcmu_ops = {
        .show_configfs_dev_params = tcmu_show_configfs_dev_params,
        .get_device_type        = sbc_get_device_type,
        .get_blocks             = tcmu_get_blocks,
-       .tb_dev_attrib_attrs    = passthrough_attrib_attrs,
+       .tb_dev_attrib_attrs    = NULL,
 };
 
 static int __init tcmu_module_init(void)
 {
-       int ret;
+       int ret, i, len = 0;
 
        BUILD_BUG_ON((sizeof(struct tcmu_cmd_entry) % TCMU_OP_ALIGN_SIZE) != 0);
 
@@ -1175,12 +1249,31 @@ static int __init tcmu_module_init(void)
                goto out_unreg_device;
        }
 
+       for (i = 0; passthrough_attrib_attrs[i] != NULL; i++) {
+               len += sizeof(struct configfs_attribute *);
+       }
+       len += sizeof(struct configfs_attribute *) * 2;
+
+       tcmu_attrs = kzalloc(len, GFP_KERNEL);
+       if (!tcmu_attrs) {
+               ret = -ENOMEM;
+               goto out_unreg_genl;
+       }
+
+       for (i = 0; passthrough_attrib_attrs[i] != NULL; i++) {
+               tcmu_attrs[i] = passthrough_attrib_attrs[i];
+       }
+       tcmu_attrs[i] = &tcmu_attr_cmd_time_out;
+       tcmu_ops.tb_dev_attrib_attrs = tcmu_attrs;
+
        ret = transport_backend_register(&tcmu_ops);
        if (ret)
-               goto out_unreg_genl;
+               goto out_attrs;
 
        return 0;
 
+out_attrs:
+       kfree(tcmu_attrs);
 out_unreg_genl:
        genl_unregister_family(&tcmu_genl_family);
 out_unreg_device:
@@ -1194,6 +1287,7 @@ out_free_cache:
 static void __exit tcmu_module_exit(void)
 {
        target_backend_unregister(&tcmu_ops);
+       kfree(tcmu_attrs);
        genl_unregister_family(&tcmu_genl_family);
        root_device_unregister(tcmu_root_device);
        kmem_cache_destroy(tcmu_cmd_cache);
index 6ee55a2d47bb429f73cf9d2b2711b109f6746a3d..e65808c482f1847d09d819a24defb0e5cf6508b5 100644 (file)
@@ -257,7 +257,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 {
        unsigned int baud = tty_termios_baud_rate(termios);
        struct dw8250_data *d = p->private_data;
-       unsigned int rate;
+       long rate;
        int ret;
 
        if (IS_ERR(d->clk) || !old)
@@ -265,7 +265,12 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 
        clk_disable_unprepare(d->clk);
        rate = clk_round_rate(d->clk, baud * 16);
-       ret = clk_set_rate(d->clk, rate);
+       if (rate < 0)
+               ret = rate;
+       else if (rate == 0)
+               ret = -ENOENT;
+       else
+               ret = clk_set_rate(d->clk, rate);
        clk_prepare_enable(d->clk);
 
        if (!ret)
index 8789ea423ccfd1054d9d5433538d0a8e466525dd..56f92d7348bf45b898b8b01a4aec813069958ec9 100644 (file)
@@ -2373,7 +2373,7 @@ static int __init pl011_console_match(struct console *co, char *name, int idx,
        if (strcmp(name, "qdf2400_e44") == 0) {
                pr_info_once("UART: Working around QDF2400 SoC erratum 44");
                qdf2400_e44_present = true;
-       } else if (strcmp(name, "pl011") != 0 || strcmp(name, "ttyAMA") != 0) {
+       } else if (strcmp(name, "pl011") != 0) {
                return -ENODEV;
        }
 
index bcf1d33e6ffe0b3cb9952e88046658df1358543b..c334bcc59c649eedc2933ac29c4dc1ef45ae21d2 100644 (file)
@@ -575,12 +575,13 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
                        pinctrl_select_state(ascport->pinctrl,
                                             ascport->states[NO_HW_FLOWCTRL]);
 
-                       gpiod = devm_get_gpiod_from_child(port->dev, "rts",
-                                                         &np->fwnode);
-                       if (!IS_ERR(gpiod)) {
-                               gpiod_direction_output(gpiod, 0);
+                       gpiod = devm_fwnode_get_gpiod_from_child(port->dev,
+                                                                "rts",
+                                                                &np->fwnode,
+                                                                GPIOD_OUT_LOW,
+                                                                np->name);
+                       if (!IS_ERR(gpiod))
                                ascport->rts = gpiod;
-                       }
                }
        }
 
index 68947f6de5ad6339adea804182597229c3eb1d38..b0500a0a87b86161b8cf8befcee9753ff6cda74d 100644 (file)
@@ -271,10 +271,13 @@ const struct file_operations tty_ldiscs_proc_fops = {
 
 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
 {
+       struct tty_ldisc *ld;
+
        ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT);
-       if (!tty->ldisc)
+       ld = tty->ldisc;
+       if (!ld)
                ldsem_up_read(&tty->ldisc_sem);
-       return tty->ldisc;
+       return ld;
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
 
@@ -488,41 +491,6 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
        tty_ldisc_debug(tty, "%p: closed\n", ld);
 }
 
-/**
- *     tty_ldisc_restore       -       helper for tty ldisc change
- *     @tty: tty to recover
- *     @old: previous ldisc
- *
- *     Restore the previous line discipline or N_TTY when a line discipline
- *     change fails due to an open error
- */
-
-static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
-{
-       struct tty_ldisc *new_ldisc;
-       int r;
-
-       /* There is an outstanding reference here so this is safe */
-       old = tty_ldisc_get(tty, old->ops->num);
-       WARN_ON(IS_ERR(old));
-       tty->ldisc = old;
-       tty_set_termios_ldisc(tty, old->ops->num);
-       if (tty_ldisc_open(tty, old) < 0) {
-               tty_ldisc_put(old);
-               /* This driver is always present */
-               new_ldisc = tty_ldisc_get(tty, N_TTY);
-               if (IS_ERR(new_ldisc))
-                       panic("n_tty: get");
-               tty->ldisc = new_ldisc;
-               tty_set_termios_ldisc(tty, N_TTY);
-               r = tty_ldisc_open(tty, new_ldisc);
-               if (r < 0)
-                       panic("Couldn't open N_TTY ldisc for "
-                             "%s --- error %d.",
-                             tty_name(tty), r);
-       }
-}
-
 /**
  *     tty_set_ldisc           -       set line discipline
  *     @tty: the terminal to set
@@ -536,12 +504,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 
 int tty_set_ldisc(struct tty_struct *tty, int disc)
 {
-       int retval;
-       struct tty_ldisc *old_ldisc, *new_ldisc;
-
-       new_ldisc = tty_ldisc_get(tty, disc);
-       if (IS_ERR(new_ldisc))
-               return PTR_ERR(new_ldisc);
+       int retval, old_disc;
 
        tty_lock(tty);
        retval = tty_ldisc_lock(tty, 5 * HZ);
@@ -554,7 +517,8 @@ int tty_set_ldisc(struct tty_struct *tty, int disc)
        }
 
        /* Check the no-op case */
-       if (tty->ldisc->ops->num == disc)
+       old_disc = tty->ldisc->ops->num;
+       if (old_disc == disc)
                goto out;
 
        if (test_bit(TTY_HUPPED, &tty->flags)) {
@@ -563,34 +527,25 @@ int tty_set_ldisc(struct tty_struct *tty, int disc)
                goto out;
        }
 
-       old_ldisc = tty->ldisc;
-
-       /* Shutdown the old discipline. */
-       tty_ldisc_close(tty, old_ldisc);
-
-       /* Now set up the new line discipline. */
-       tty->ldisc = new_ldisc;
-       tty_set_termios_ldisc(tty, disc);
-
-       retval = tty_ldisc_open(tty, new_ldisc);
+       retval = tty_ldisc_reinit(tty, disc);
        if (retval < 0) {
                /* Back to the old one or N_TTY if we can't */
-               tty_ldisc_put(new_ldisc);
-               tty_ldisc_restore(tty, old_ldisc);
+               if (tty_ldisc_reinit(tty, old_disc) < 0) {
+                       pr_err("tty: TIOCSETD failed, reinitializing N_TTY\n");
+                       if (tty_ldisc_reinit(tty, N_TTY) < 0) {
+                               /* At this point we have tty->ldisc == NULL. */
+                               pr_err("tty: reinitializing N_TTY failed\n");
+                       }
+               }
        }
 
-       if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc) {
+       if (tty->ldisc && tty->ldisc->ops->num != old_disc &&
+           tty->ops->set_ldisc) {
                down_read(&tty->termios_rwsem);
                tty->ops->set_ldisc(tty);
                up_read(&tty->termios_rwsem);
        }
 
-       /* At this point we hold a reference to the new ldisc and a
-          reference to the old ldisc, or we hold two references to
-          the old ldisc (if it was restored as part of error cleanup
-          above). In either case, releasing a single reference from
-          the old ldisc is correct. */
-       new_ldisc = old_ldisc;
 out:
        tty_ldisc_unlock(tty);
 
@@ -598,7 +553,6 @@ out:
           already running */
        tty_buffer_restart_work(tty->port);
 err:
-       tty_ldisc_put(new_ldisc);       /* drop the extra reference */
        tty_unlock(tty);
        return retval;
 }
@@ -659,10 +613,8 @@ int tty_ldisc_reinit(struct tty_struct *tty, int disc)
        int retval;
 
        ld = tty_ldisc_get(tty, disc);
-       if (IS_ERR(ld)) {
-               BUG_ON(disc == N_TTY);
+       if (IS_ERR(ld))
                return PTR_ERR(ld);
-       }
 
        if (tty->ldisc) {
                tty_ldisc_close(tty, tty->ldisc);
@@ -674,10 +626,8 @@ int tty_ldisc_reinit(struct tty_struct *tty, int disc)
        tty_set_termios_ldisc(tty, disc);
        retval = tty_ldisc_open(tty, tty->ldisc);
        if (retval) {
-               if (!WARN_ON(disc == N_TTY)) {
-                       tty_ldisc_put(tty->ldisc);
-                       tty->ldisc = NULL;
-               }
+               tty_ldisc_put(tty->ldisc);
+               tty->ldisc = NULL;
        }
        return retval;
 }
index f03692ec552056845c6fa50947e38abca47ea66b..8fb309a0ff6b5dae0c6f867cd323585aeff17252 100644 (file)
@@ -1381,7 +1381,7 @@ static int usbtmc_probe(struct usb_interface *intf,
 
        dev_dbg(&intf->dev, "%s called\n", __func__);
 
-       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
@@ -1444,6 +1444,13 @@ static int usbtmc_probe(struct usb_interface *intf,
                        break;
                }
        }
+
+       if (!data->bulk_out || !data->bulk_in) {
+               dev_err(&intf->dev, "bulk endpoints not found\n");
+               retcode = -ENODEV;
+               goto err_put;
+       }
+
        /* Find int endpoint */
        for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) {
                endpoint = &iface_desc->endpoint[n].desc;
@@ -1469,8 +1476,10 @@ static int usbtmc_probe(struct usb_interface *intf,
        if (data->iin_ep_present) {
                /* allocate int urb */
                data->iin_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!data->iin_urb)
+               if (!data->iin_urb) {
+                       retcode = -ENOMEM;
                        goto error_register;
+               }
 
                /* Protect interrupt in endpoint data until iin_urb is freed */
                kref_get(&data->kref);
@@ -1478,8 +1487,10 @@ static int usbtmc_probe(struct usb_interface *intf,
                /* allocate buffer for interrupt in */
                data->iin_buffer = kmalloc(data->iin_wMaxPacketSize,
                                        GFP_KERNEL);
-               if (!data->iin_buffer)
+               if (!data->iin_buffer) {
+                       retcode = -ENOMEM;
                        goto error_register;
+               }
 
                /* fill interrupt urb */
                usb_fill_int_urb(data->iin_urb, data->usb_dev,
@@ -1512,6 +1523,7 @@ error_register:
        sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
        sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
        usbtmc_free_int(data);
+err_put:
        kref_put(&data->kref, usbtmc_delete);
        return retcode;
 }
index 25dbd8c7aec73345d357c2a75ff0cde26c918217..4be52c602e9b7a7de6a76ecb4be686cb12ec9950 100644 (file)
@@ -280,6 +280,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
 
                        /*
                         * Adjust bInterval for quirked devices.
+                        */
+                       /*
+                        * This quirk fixes bIntervals reported in ms.
+                        */
+                       if (to_usb_device(ddev)->quirks &
+                               USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
+                               n = clamp(fls(d->bInterval) + 3, i, j);
+                               i = j = n;
+                       }
+                       /*
                         * This quirk fixes bIntervals reported in
                         * linear microframes.
                         */
index f0dd08198d7426b9973bb676bca12b8cb76d7e7b..5286bf67869a83e1d7e1d3f1ca0ebc87db5cf7a4 100644 (file)
@@ -4275,7 +4275,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
        struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
        int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
 
-       if (!udev->usb2_hw_lpm_capable)
+       if (!udev->usb2_hw_lpm_capable || !udev->bos)
                return;
 
        if (hub)
index 24f9f98968a5d860f83920287a5b7deb4c98bed6..96b21b0dac1e8c15fb20c19c85d13a58ab95b285 100644 (file)
@@ -170,6 +170,14 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* M-Systems Flash Disk Pioneers */
        { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Baum Vario Ultra */
+       { USB_DEVICE(0x0904, 0x6101), .driver_info =
+                       USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+       { USB_DEVICE(0x0904, 0x6102), .driver_info =
+                       USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+       { USB_DEVICE(0x0904, 0x6103), .driver_info =
+                       USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
+
        /* Keytouch QWERTY Panel keyboard */
        { USB_DEVICE(0x0926, 0x3333), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index 0d75158e43fe4807569db4d10204cee406b097b7..79e7a3480d51b07abf3988a51f1790f6caec7ca3 100644 (file)
@@ -171,6 +171,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
                int status)
 {
        struct dwc3                     *dwc = dep->dwc;
+       unsigned int                    unmap_after_complete = false;
 
        req->started = false;
        list_del(&req->list);
@@ -180,11 +181,19 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
 
-       if (dwc->ep0_bounced && dep->number <= 1)
+       /*
+        * NOTICE we don't want to unmap before calling ->complete() if we're
+        * dealing with a bounced ep0 request. If we unmap it here, we would end
+        * up overwritting the contents of req->buf and this could confuse the
+        * gadget driver.
+        */
+       if (dwc->ep0_bounced && dep->number <= 1) {
                dwc->ep0_bounced = false;
-
-       usb_gadget_unmap_request_by_dev(dwc->sysdev,
-                       &req->request, req->direction);
+               unmap_after_complete = true;
+       } else {
+               usb_gadget_unmap_request_by_dev(dwc->sysdev,
+                               &req->request, req->direction);
+       }
 
        trace_dwc3_gadget_giveback(req);
 
@@ -192,6 +201,10 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
        usb_gadget_giveback_request(&dep->endpoint, &req->request);
        spin_lock(&dwc->lock);
 
+       if (unmap_after_complete)
+               usb_gadget_unmap_request_by_dev(dwc->sysdev,
+                               &req->request, req->direction);
+
        if (dep->number > 1)
                pm_runtime_put(dwc->dev);
 }
index a30766ca422644ce91be7660b8822b4a7357f7f3..5e3828d9dac7f3af922456d141191ddd0733bbaf 100644 (file)
@@ -535,13 +535,15 @@ static int acm_notify_serial_state(struct f_acm *acm)
 {
        struct usb_composite_dev *cdev = acm->port.func.config->cdev;
        int                     status;
+       __le16                  serial_state;
 
        spin_lock(&acm->lock);
        if (acm->notify_req) {
                dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n",
                        acm->port_num, acm->serial_state);
+               serial_state = cpu_to_le16(acm->serial_state);
                status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
-                               0, &acm->serial_state, sizeof(acm->serial_state));
+                               0, &serial_state, sizeof(acm->serial_state));
        } else {
                acm->pending = true;
                status = 0;
index 89b48bcc377a16d426d6f5826a2e1ce5301124b6..5eea44823ca06d06955eb2bc51782cac6cd345ec 100644 (file)
@@ -367,7 +367,7 @@ try_again:
        count  = min_t(unsigned, count, hidg->report_length);
 
        spin_unlock_irqrestore(&hidg->write_spinlock, flags);
-       status = copy_from_user(hidg->req->buf, buffer, count);
+       status = copy_from_user(req->buf, buffer, count);
 
        if (status != 0) {
                ERROR(hidg->func.config->cdev,
@@ -378,9 +378,9 @@ try_again:
 
        spin_lock_irqsave(&hidg->write_spinlock, flags);
 
-       /* we our function has been disabled by host */
+       /* when our function has been disabled by host */
        if (!hidg->req) {
-               free_ep_req(hidg->in_ep, hidg->req);
+               free_ep_req(hidg->in_ep, req);
                /*
                 * TODO
                 * Should we fail with error here?
@@ -394,7 +394,7 @@ try_again:
        req->complete = f_hidg_req_complete;
        req->context  = hidg;
 
-       status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
+       status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
        if (status < 0) {
                ERROR(hidg->func.config->cdev,
                        "usb_ep_queue error on int endpoint %zd\n", status);
index 29b41b5dee04d2e0e3e87a6dc97d6dde84af49d0..f8a1881609a2c808f690f6d31ea6bcaf118b8bb4 100644 (file)
@@ -594,6 +594,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U);
        opts->streaming_maxburst = min(opts->streaming_maxburst, 15U);
 
+       /* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */
+       if (opts->streaming_maxburst &&
+           (opts->streaming_maxpacket % 1024) != 0) {
+               opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024);
+               INFO(cdev, "overriding streaming_maxpacket to %d\n",
+                    opts->streaming_maxpacket);
+       }
+
        /* Fill in the FS/HS/SS Video Streaming specific descriptors from the
         * module parameters.
         *
@@ -625,7 +633,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
        uvc_ss_streaming_comp.wBytesPerInterval =
                cpu_to_le16(max_packet_size * max_packet_mult *
-                           opts->streaming_maxburst);
+                           (opts->streaming_maxburst + 1));
 
        /* Allocate endpoints. */
        ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
index a97da645c1b9eaecc5e5bb0bcb5ad25857c43ec8..8a365aad66fe2e38eaf0a869ae0f774349f694f2 100644 (file)
@@ -1523,7 +1523,6 @@ static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
                td = phys_to_virt(addr);
                addr2 = (dma_addr_t)td->next;
                pci_pool_free(dev->data_requests, td, addr);
-               td->next = 0x00;
                addr = addr2;
        }
        req->chain_len = 1;
index 8b9fd7534f698b937b5a89113acc12c716368075..502bfe30a077a20120616af74b378c62bc2ec6d9 100644 (file)
@@ -347,6 +347,9 @@ static int idmouse_probe(struct usb_interface *interface,
        if (iface_desc->desc.bInterfaceClass != 0x0A)
                return -ENODEV;
 
+       if (iface_desc->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        /* allocate memory for our device state and initialize it */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL)
index 77176511658f3328f830ecdbd056f072a6c84f8a..d3d12475326663def2ce1f389f06f040d2a56126 100644 (file)
@@ -366,6 +366,10 @@ static int lvs_rh_probe(struct usb_interface *intf,
 
        hdev = interface_to_usbdev(intf);
        desc = intf->cur_altsetting;
+
+       if (desc->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        endpoint = &desc->endpoint[0].desc;
 
        /* valid only for SS root hub */
index e45a3a680db8f6490257c0f6decdfd6d1d8247d8..07014cad6dbe357bca938561eaf976dbbee902d4 100644 (file)
@@ -709,6 +709,11 @@ static int uss720_probe(struct usb_interface *intf,
 
        interface = intf->cur_altsetting;
 
+       if (interface->desc.bNumEndpoints < 3) {
+               usb_put_dev(usbdev);
+               return -ENODEV;
+       }
+
        /*
         * Allocate parport interface 
         */
index d8bae6ca890475b16bf7d45058ae35713ca46656..0c3664ab705eed549e73d53dea13976066182ee1 100644 (file)
@@ -2490,8 +2490,8 @@ static int musb_remove(struct platform_device *pdev)
        musb_host_cleanup(musb);
        musb_gadget_cleanup(musb);
 
-       spin_lock_irqsave(&musb->lock, flags);
        musb_platform_disable(musb);
+       spin_lock_irqsave(&musb->lock, flags);
        musb_disable_interrupts(musb);
        musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
        spin_unlock_irqrestore(&musb->lock, flags);
index 00e272bfee39a94520f16aeef03beed6a08ea43c..355655f8a3fbc9c4e3d8acd03eefa31a5736fb2f 100644 (file)
@@ -238,8 +238,27 @@ static void cppi41_dma_callback(void *private_data,
                        transferred < cppi41_channel->packet_sz)
                cppi41_channel->prog_len = 0;
 
-       if (cppi41_channel->is_tx)
-               empty = musb_is_tx_fifo_empty(hw_ep);
+       if (cppi41_channel->is_tx) {
+               u8 type;
+
+               if (is_host_active(musb))
+                       type = hw_ep->out_qh->type;
+               else
+                       type = hw_ep->ep_in.type;
+
+               if (type == USB_ENDPOINT_XFER_ISOC)
+                       /*
+                        * Don't use the early-TX-interrupt workaround below
+                        * for Isoch transfter. Since Isoch are periodic
+                        * transfer, by the time the next transfer is
+                        * scheduled, the current one should be done already.
+                        *
+                        * This avoids audio playback underrun issue.
+                        */
+                       empty = true;
+               else
+                       empty = musb_is_tx_fifo_empty(hw_ep);
+       }
 
        if (!cppi41_channel->is_tx || empty) {
                cppi41_trans_done(cppi41_channel);
index 7c047c4a2565cca25690c47d85a2bb9eb29f728e..9c7ee26ef388062bdc5e1f1fb2097fc010882950 100644 (file)
@@ -933,7 +933,7 @@ static int dsps_probe(struct platform_device *pdev)
        if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
                ret = dsps_setup_optional_vbus_irq(pdev, glue);
                if (ret)
-                       return ret;
+                       goto err_iounmap;
        }
 
        platform_set_drvdata(pdev, glue);
@@ -946,6 +946,8 @@ static int dsps_probe(struct platform_device *pdev)
 
 err:
        pm_runtime_disable(&pdev->dev);
+err_iounmap:
+       iounmap(glue->usbss_base);
        return ret;
 }
 
@@ -956,6 +958,7 @@ static int dsps_remove(struct platform_device *pdev)
        platform_device_unregister(glue->musb);
 
        pm_runtime_disable(&pdev->dev);
+       iounmap(glue->usbss_base);
 
        return 0;
 }
index 42cc72e54c051b2115c358bcee8bfc534258d206..af67a0de6b5d475d2be95952ddfb2354546a0fbb 100644 (file)
@@ -233,6 +233,14 @@ static void option_instat_callback(struct urb *urb);
 #define BANDRICH_PRODUCT_1012                  0x1012
 
 #define QUALCOMM_VENDOR_ID                     0x05C6
+/* These Quectel products use Qualcomm's vendor ID */
+#define QUECTEL_PRODUCT_UC20                   0x9003
+#define QUECTEL_PRODUCT_UC15                   0x9090
+
+#define QUECTEL_VENDOR_ID                      0x2c7c
+/* These Quectel products use Quectel's vendor ID */
+#define QUECTEL_PRODUCT_EC21                   0x0121
+#define QUECTEL_PRODUCT_EC25                   0x0125
 
 #define CMOTECH_VENDOR_ID                      0x16d8
 #define CMOTECH_PRODUCT_6001                   0x6001
@@ -1161,7 +1169,14 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
-       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
+       /* Quectel products using Qualcomm vendor ID */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       /* Quectel products using Quectel vendor ID */
+       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
index 696458db7e3c45e661a9825d05df0fe25dc0a832..38b3f0d8cd580f2366136003934d00a475b1d7f1 100644 (file)
@@ -169,6 +169,8 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x413c, 0x81a9)},   /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81b1)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81b3)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
+       {DEVICE_SWI(0x413c, 0x81b5)},   /* Dell Wireless 5811e QDL */
+       {DEVICE_SWI(0x413c, 0x81b6)},   /* Dell Wireless 5811e QDL */
 
        /* Huawei devices */
        {DEVICE_HWI(0x03f0, 0x581d)},   /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
index 252c7bd9218afd5db373325b55b561c304ab0e88..d01496fd27fe88460988745a57c32c0cf5f14840 100644 (file)
@@ -39,6 +39,9 @@ int wa_create(struct wahc *wa, struct usb_interface *iface,
        int result;
        struct device *dev = &iface->dev;
 
+       if (iface->cur_altsetting->desc.bNumEndpoints < 3)
+               return -ENODEV;
+
        result = wa_rpipes_create(wa);
        if (result < 0)
                goto error_rpipes_create;
index 0aa6c3c29d17260f684b8bf79944eff43af04427..35a1e777b4497ad0ad1cfa18db0834354732b128 100644 (file)
@@ -823,6 +823,9 @@ static int hwarc_probe(struct usb_interface *iface,
        struct hwarc *hwarc;
        struct device *dev = &iface->dev;
 
+       if (iface->cur_altsetting->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        result = -ENOMEM;
        uwb_rc = uwb_rc_alloc();
        if (uwb_rc == NULL) {
index 2bfc846ac071341ace37aa50dc126fc5b08a519f..6345e85822a42457f11c607effb3fbb66ce8c89f 100644 (file)
@@ -362,6 +362,9 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
                                 result);
        }
 
+       if (iface->cur_altsetting->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        result = -ENOMEM;
        i1480_usb = kzalloc(sizeof(*i1480_usb), GFP_KERNEL);
        if (i1480_usb == NULL) {
index 609f4f982c74c59a5b4fd87dfd83367765ebbc1e..561084ab387f3fd7c8ae3fa3e91c27d8329f7fe4 100644 (file)
@@ -403,6 +403,7 @@ static void vfio_group_release(struct kref *kref)
        struct iommu_group *iommu_group = group->iommu_group;
 
        WARN_ON(!list_empty(&group->device_list));
+       WARN_ON(group->notifier.head);
 
        list_for_each_entry_safe(unbound, tmp,
                                 &group->unbound_list, unbound_next) {
@@ -1573,6 +1574,10 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
                return -EBUSY;
        }
 
+       /* Warn if previous user didn't cleanup and re-init to drop them */
+       if (WARN_ON(group->notifier.head))
+               BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier);
+
        filep->private_data = group;
 
        return 0;
@@ -1584,9 +1589,6 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
 
        filep->private_data = NULL;
 
-       /* Any user didn't unregister? */
-       WARN_ON(group->notifier.head);
-
        vfio_group_try_dissolve_container(group);
 
        atomic_dec(&group->opened);
index c26fa1f3ed8606e65870f05aa47b7eca5fdf381e..32d2633092a37edf64ec4b9d2afc9fa4f12ea77d 100644 (file)
@@ -1182,8 +1182,7 @@ static struct vfio_group *find_iommu_group(struct vfio_domain *domain,
        return NULL;
 }
 
-static bool vfio_iommu_has_resv_msi(struct iommu_group *group,
-                                   phys_addr_t *base)
+static bool vfio_iommu_has_sw_msi(struct iommu_group *group, phys_addr_t *base)
 {
        struct list_head group_resv_regions;
        struct iommu_resv_region *region, *next;
@@ -1192,7 +1191,7 @@ static bool vfio_iommu_has_resv_msi(struct iommu_group *group,
        INIT_LIST_HEAD(&group_resv_regions);
        iommu_get_group_resv_regions(group, &group_resv_regions);
        list_for_each_entry(region, &group_resv_regions, list) {
-               if (region->type & IOMMU_RESV_MSI) {
+               if (region->type == IOMMU_RESV_SW_MSI) {
                        *base = region->start;
                        ret = true;
                        goto out;
@@ -1283,7 +1282,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
        if (ret)
                goto out_domain;
 
-       resv_msi = vfio_iommu_has_resv_msi(iommu_group, &resv_msi_base);
+       resv_msi = vfio_iommu_has_sw_msi(iommu_group, &resv_msi_base);
 
        INIT_LIST_HEAD(&domain->group_list);
        list_add(&group->next, &domain->group_list);
index ce5e63d2c66aac7d019c422ec294cab025e94e5e..44eed8eb0725b25e3c9765e19387e7c338ab9bbb 100644 (file)
@@ -223,6 +223,46 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
        return len;
 }
 
+static int
+vhost_transport_cancel_pkt(struct vsock_sock *vsk)
+{
+       struct vhost_vsock *vsock;
+       struct virtio_vsock_pkt *pkt, *n;
+       int cnt = 0;
+       LIST_HEAD(freeme);
+
+       /* Find the vhost_vsock according to guest context id  */
+       vsock = vhost_vsock_get(vsk->remote_addr.svm_cid);
+       if (!vsock)
+               return -ENODEV;
+
+       spin_lock_bh(&vsock->send_pkt_list_lock);
+       list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) {
+               if (pkt->vsk != vsk)
+                       continue;
+               list_move(&pkt->list, &freeme);
+       }
+       spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+       list_for_each_entry_safe(pkt, n, &freeme, list) {
+               if (pkt->reply)
+                       cnt++;
+               list_del(&pkt->list);
+               virtio_transport_free_pkt(pkt);
+       }
+
+       if (cnt) {
+               struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX];
+               int new_cnt;
+
+               new_cnt = atomic_sub_return(cnt, &vsock->queued_replies);
+               if (new_cnt + cnt >= tx_vq->num && new_cnt < tx_vq->num)
+                       vhost_poll_queue(&tx_vq->poll);
+       }
+
+       return 0;
+}
+
 static struct virtio_vsock_pkt *
 vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq,
                      unsigned int out, unsigned int in)
@@ -675,6 +715,7 @@ static struct virtio_transport vhost_transport = {
                .release                  = virtio_transport_release,
                .connect                  = virtio_transport_connect,
                .shutdown                 = virtio_transport_shutdown,
+               .cancel_pkt               = vhost_transport_cancel_pkt,
 
                .dgram_enqueue            = virtio_transport_dgram_enqueue,
                .dgram_dequeue            = virtio_transport_dgram_dequeue,
index c77a0751a31173344de0c02c3f70d18ec259ca63..f3bf8f4e2d6cef09101b53aa9f1a69563b206287 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
+#include <linux/refcount.h>
 
 #include <xen/xen.h>
 #include <xen/grant_table.h>
@@ -86,7 +87,7 @@ struct grant_map {
        int index;
        int count;
        int flags;
-       atomic_t users;
+       refcount_t users;
        struct unmap_notify notify;
        struct ioctl_gntdev_grant_ref *grants;
        struct gnttab_map_grant_ref   *map_ops;
@@ -166,7 +167,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 
        add->index = 0;
        add->count = count;
-       atomic_set(&add->users, 1);
+       refcount_set(&add->users, 1);
 
        return add;
 
@@ -212,7 +213,7 @@ static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map)
        if (!map)
                return;
 
-       if (!atomic_dec_and_test(&map->users))
+       if (!refcount_dec_and_test(&map->users))
                return;
 
        atomic_sub(map->count, &pages_mapped);
@@ -400,7 +401,7 @@ static void gntdev_vma_open(struct vm_area_struct *vma)
        struct grant_map *map = vma->vm_private_data;
 
        pr_debug("gntdev_vma_open %p\n", vma);
-       atomic_inc(&map->users);
+       refcount_inc(&map->users);
 }
 
 static void gntdev_vma_close(struct vm_area_struct *vma)
@@ -1004,7 +1005,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
                goto unlock_out;
        }
 
-       atomic_inc(&map->users);
+       refcount_inc(&map->users);
 
        vma->vm_ops = &gntdev_vmops;
 
index 4ce10bcca18b1f600c351675142240dbe94a4022..23e391d3ec015d0c5b38b21619898c282826f59c 100644 (file)
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/syscore_ops.h>
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #include <xen/xen.h>
-#include <xen/xen-ops.h>
 #include <xen/interface/platform.h>
 #include <asm/xen/hypercall.h>
 
@@ -408,7 +408,7 @@ static int check_acpi_ids(struct acpi_processor *pr_backup)
        acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
                            read_acpi_id, NULL, NULL, NULL);
-       acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL);
+       acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, read_acpi_id, NULL, NULL);
 
 upload:
        if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) {
@@ -466,15 +466,33 @@ static int xen_upload_processor_pm_data(void)
        return rc;
 }
 
-static int xen_acpi_processor_resume(struct notifier_block *nb,
-                                    unsigned long action, void *data)
+static void xen_acpi_processor_resume_worker(struct work_struct *dummy)
 {
+       int rc;
+
        bitmap_zero(acpi_ids_done, nr_acpi_bits);
-       return xen_upload_processor_pm_data();
+
+       rc = xen_upload_processor_pm_data();
+       if (rc != 0)
+               pr_info("ACPI data upload failed, error = %d\n", rc);
+}
+
+static void xen_acpi_processor_resume(void)
+{
+       static DECLARE_WORK(wq, xen_acpi_processor_resume_worker);
+
+       /*
+        * xen_upload_processor_pm_data() calls non-atomic code.
+        * However, the context for xen_acpi_processor_resume is syscore
+        * with only the boot CPU online and in an atomic context.
+        *
+        * So defer the upload for some point safer.
+        */
+       schedule_work(&wq);
 }
 
-struct notifier_block xen_acpi_processor_resume_nb = {
-       .notifier_call = xen_acpi_processor_resume,
+static struct syscore_ops xap_syscore_ops = {
+       .resume = xen_acpi_processor_resume,
 };
 
 static int __init xen_acpi_processor_init(void)
@@ -527,7 +545,7 @@ static int __init xen_acpi_processor_init(void)
        if (rc)
                goto err_unregister;
 
-       xen_resume_notifier_register(&xen_acpi_processor_resume_nb);
+       register_syscore_ops(&xap_syscore_ops);
 
        return 0;
 err_unregister:
@@ -544,7 +562,7 @@ static void __exit xen_acpi_processor_exit(void)
 {
        int i;
 
-       xen_resume_notifier_unregister(&xen_acpi_processor_resume_nb);
+       unregister_syscore_ops(&xap_syscore_ops);
        kfree(acpi_ids_done);
        kfree(acpi_id_present);
        kfree(acpi_id_cst_present);
index b29447e03ede0d638950fa0dd64d908004156ea6..25d404d22caebcfd6b6b60d6287e36258f1185eb 100644 (file)
@@ -362,7 +362,7 @@ static void afs_callback_updater(struct work_struct *work)
 {
        struct afs_server *server;
        struct afs_vnode *vnode, *xvnode;
-       time_t now;
+       time64_t now;
        long timeout;
        int ret;
 
@@ -370,7 +370,7 @@ static void afs_callback_updater(struct work_struct *work)
 
        _enter("");
 
-       now = get_seconds();
+       now = ktime_get_real_seconds();
 
        /* find the first vnode to update */
        spin_lock(&server->cb_lock);
@@ -424,7 +424,8 @@ static void afs_callback_updater(struct work_struct *work)
 
        /* and then reschedule */
        _debug("reschedule");
-       vnode->update_at = get_seconds() + afs_vnode_update_timeout;
+       vnode->update_at = ktime_get_real_seconds() +
+                       afs_vnode_update_timeout;
 
        spin_lock(&server->cb_lock);
 
index 2edbdcbf6432add190464b5a5f414592953c944a..3062cceb5c2aebcc4a15e3c52d1b26ecea82f20d 100644 (file)
@@ -187,7 +187,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
        struct afs_callback *cb;
        struct afs_server *server;
        __be32 *bp;
-       u32 tmp;
        int ret, loop;
 
        _enter("{%u}", call->unmarshall);
@@ -249,9 +248,9 @@ static int afs_deliver_cb_callback(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               tmp = ntohl(call->tmp);
-               _debug("CB count: %u", tmp);
-               if (tmp != call->count && tmp != 0)
+               call->count2 = ntohl(call->tmp);
+               _debug("CB count: %u", call->count2);
+               if (call->count2 != call->count && call->count2 != 0)
                        return -EBADMSG;
                call->offset = 0;
                call->unmarshall++;
@@ -259,14 +258,14 @@ static int afs_deliver_cb_callback(struct afs_call *call)
        case 4:
                _debug("extract CB array");
                ret = afs_extract_data(call, call->buffer,
-                                      call->count * 3 * 4, false);
+                                      call->count2 * 3 * 4, false);
                if (ret < 0)
                        return ret;
 
                _debug("unmarshall CB array");
                cb = call->request;
                bp = call->buffer;
-               for (loop = call->count; loop > 0; loop--, cb++) {
+               for (loop = call->count2; loop > 0; loop--, cb++) {
                        cb->version     = ntohl(*bp++);
                        cb->expiry      = ntohl(*bp++);
                        cb->type        = ntohl(*bp++);
index ba7b71fba34bcc4cd5f8b8a305ace06a388ac607..0d5b8508869bf0642a88d4c87b3feb49c1fab433 100644 (file)
@@ -30,6 +30,7 @@ static int afs_readpages(struct file *filp, struct address_space *mapping,
 
 const struct file_operations afs_file_operations = {
        .open           = afs_open,
+       .flush          = afs_flush,
        .release        = afs_release,
        .llseek         = generic_file_llseek,
        .read_iter      = generic_file_read_iter,
@@ -184,10 +185,13 @@ int afs_page_filler(void *data, struct page *page)
                if (!req)
                        goto enomem;
 
+               /* We request a full page.  If the page is a partial one at the
+                * end of the file, the server will return a short read and the
+                * unmarshalling code will clear the unfilled space.
+                */
                atomic_set(&req->usage, 1);
                req->pos = (loff_t)page->index << PAGE_SHIFT;
-               req->len = min_t(size_t, i_size_read(inode) - req->pos,
-                                PAGE_SIZE);
+               req->len = PAGE_SIZE;
                req->nr_pages = 1;
                req->pages[0] = page;
                get_page(page);
@@ -208,7 +212,13 @@ int afs_page_filler(void *data, struct page *page)
                        fscache_uncache_page(vnode->cache, page);
 #endif
                        BUG_ON(PageFsCache(page));
-                       goto error;
+
+                       if (ret == -EINTR ||
+                           ret == -ENOMEM ||
+                           ret == -ERESTARTSYS ||
+                           ret == -EAGAIN)
+                               goto error;
+                       goto io_error;
                }
 
                SetPageUptodate(page);
@@ -227,10 +237,12 @@ int afs_page_filler(void *data, struct page *page)
        _leave(" = 0");
        return 0;
 
+io_error:
+       SetPageError(page);
+       goto error;
 enomem:
        ret = -ENOMEM;
 error:
-       SetPageError(page);
        unlock_page(page);
        _leave(" = %d", ret);
        return ret;
index ac8e766978dc440e8690fbf44333d41f9894f92a..19f76ae36982df43be740c1bf73d396b1a81c77c 100644 (file)
 #include "internal.h"
 #include "afs_fs.h"
 
+/*
+ * We need somewhere to discard into in case the server helpfully returns more
+ * than we asked for in FS.FetchData{,64}.
+ */
+static u8 afs_discard_buffer[64];
+
 /*
  * decode an AFSFid block
  */
@@ -105,7 +111,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
                        vnode->vfs_inode.i_mode = mode;
                }
 
-               vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server;
+               vnode->vfs_inode.i_ctime.tv_sec = status->mtime_client;
                vnode->vfs_inode.i_mtime        = vnode->vfs_inode.i_ctime;
                vnode->vfs_inode.i_atime        = vnode->vfs_inode.i_ctime;
                vnode->vfs_inode.i_version      = data_version;
@@ -139,7 +145,7 @@ static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
        vnode->cb_version       = ntohl(*bp++);
        vnode->cb_expiry        = ntohl(*bp++);
        vnode->cb_type          = ntohl(*bp++);
-       vnode->cb_expires       = vnode->cb_expiry + get_seconds();
+       vnode->cb_expires       = vnode->cb_expiry + ktime_get_real_seconds();
        *_bp = bp;
 }
 
@@ -315,7 +321,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
        void *buffer;
        int ret;
 
-       _enter("{%u,%zu/%u;%u/%llu}",
+       _enter("{%u,%zu/%u;%llu/%llu}",
               call->unmarshall, call->offset, call->count,
               req->remain, req->actual_len);
 
@@ -353,12 +359,6 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
 
                req->actual_len |= ntohl(call->tmp);
                _debug("DATA length: %llu", req->actual_len);
-               /* Check that the server didn't want to send us extra.  We
-                * might want to just discard instead, but that requires
-                * cooperation from AF_RXRPC.
-                */
-               if (req->actual_len > req->len)
-                       return -EBADMSG;
 
                req->remain = req->actual_len;
                call->offset = req->pos & (PAGE_SIZE - 1);
@@ -368,6 +368,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                call->unmarshall++;
 
        begin_page:
+               ASSERTCMP(req->index, <, req->nr_pages);
                if (req->remain > PAGE_SIZE - call->offset)
                        size = PAGE_SIZE - call->offset;
                else
@@ -378,7 +379,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
 
                /* extract the returned data */
        case 3:
-               _debug("extract data %u/%llu %zu/%u",
+               _debug("extract data %llu/%llu %zu/%u",
                       req->remain, req->actual_len, call->offset, call->count);
 
                buffer = kmap(req->pages[req->index]);
@@ -389,19 +390,40 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                if (call->offset == PAGE_SIZE) {
                        if (req->page_done)
                                req->page_done(call, req);
+                       req->index++;
                        if (req->remain > 0) {
-                               req->index++;
                                call->offset = 0;
+                               if (req->index >= req->nr_pages) {
+                                       call->unmarshall = 4;
+                                       goto begin_discard;
+                               }
                                goto begin_page;
                        }
                }
+               goto no_more_data;
+
+               /* Discard any excess data the server gave us */
+       begin_discard:
+       case 4:
+               size = min_t(loff_t, sizeof(afs_discard_buffer), req->remain);
+               call->count = size;
+               _debug("extract discard %llu/%llu %zu/%u",
+                      req->remain, req->actual_len, call->offset, call->count);
+
+               call->offset = 0;
+               ret = afs_extract_data(call, afs_discard_buffer, call->count, true);
+               req->remain -= call->offset;
+               if (ret < 0)
+                       return ret;
+               if (req->remain > 0)
+                       goto begin_discard;
 
        no_more_data:
                call->offset = 0;
-               call->unmarshall++;
+               call->unmarshall = 5;
 
                /* extract the metadata */
-       case 4:
+       case 5:
                ret = afs_extract_data(call, call->buffer,
                                       (21 + 3 + 6) * 4, false);
                if (ret < 0)
@@ -416,16 +438,17 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                call->offset = 0;
                call->unmarshall++;
 
-       case 5:
+       case 6:
                break;
        }
 
-       if (call->count < PAGE_SIZE) {
-               buffer = kmap(req->pages[req->index]);
-               memset(buffer + call->count, 0, PAGE_SIZE - call->count);
-               kunmap(req->pages[req->index]);
+       for (; req->index < req->nr_pages; req->index++) {
+               if (call->count < PAGE_SIZE)
+                       zero_user_segment(req->pages[req->index],
+                                         call->count, PAGE_SIZE);
                if (req->page_done)
                        req->page_done(call, req);
+               call->count = 0;
        }
 
        _leave(" = 0 [done]");
@@ -711,8 +734,8 @@ int afs_fs_create(struct afs_server *server,
                memset(bp, 0, padsz);
                bp = (void *) bp + padsz;
        }
-       *bp++ = htonl(AFS_SET_MODE);
-       *bp++ = 0; /* mtime */
+       *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
+       *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
        *bp++ = 0; /* owner */
        *bp++ = 0; /* group */
        *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
@@ -980,8 +1003,8 @@ int afs_fs_symlink(struct afs_server *server,
                memset(bp, 0, c_padsz);
                bp = (void *) bp + c_padsz;
        }
-       *bp++ = htonl(AFS_SET_MODE);
-       *bp++ = 0; /* mtime */
+       *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
+       *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
        *bp++ = 0; /* owner */
        *bp++ = 0; /* group */
        *bp++ = htonl(S_IRWXUGO); /* unix mode */
@@ -1180,8 +1203,8 @@ static int afs_fs_store_data64(struct afs_server *server,
        *bp++ = htonl(vnode->fid.vnode);
        *bp++ = htonl(vnode->fid.unique);
 
-       *bp++ = 0; /* mask */
-       *bp++ = 0; /* mtime */
+       *bp++ = htonl(AFS_SET_MTIME); /* mask */
+       *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
        *bp++ = 0; /* owner */
        *bp++ = 0; /* group */
        *bp++ = 0; /* unix mode */
@@ -1213,7 +1236,7 @@ int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
        _enter(",%x,{%x:%u},,",
               key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
 
-       size = to - offset;
+       size = (loff_t)to - (loff_t)offset;
        if (first != last)
                size += (loff_t)(last - first) << PAGE_SHIFT;
        pos = (loff_t)first << PAGE_SHIFT;
@@ -1257,8 +1280,8 @@ int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
        *bp++ = htonl(vnode->fid.vnode);
        *bp++ = htonl(vnode->fid.unique);
 
-       *bp++ = 0; /* mask */
-       *bp++ = 0; /* mtime */
+       *bp++ = htonl(AFS_SET_MTIME); /* mask */
+       *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
        *bp++ = 0; /* owner */
        *bp++ = 0; /* group */
        *bp++ = 0; /* unix mode */
index 1e4897a048d2ee0dee49b613f22336b7118ff9f8..aae55dd151087e16f123adc0ebe51e47e393b297 100644 (file)
@@ -54,8 +54,21 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
                inode->i_fop    = &afs_dir_file_operations;
                break;
        case AFS_FTYPE_SYMLINK:
-               inode->i_mode   = S_IFLNK | vnode->status.mode;
-               inode->i_op     = &page_symlink_inode_operations;
+               /* Symlinks with a mode of 0644 are actually mountpoints. */
+               if ((vnode->status.mode & 0777) == 0644) {
+                       inode->i_flags |= S_AUTOMOUNT;
+
+                       spin_lock(&vnode->lock);
+                       set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
+                       spin_unlock(&vnode->lock);
+
+                       inode->i_mode   = S_IFDIR | 0555;
+                       inode->i_op     = &afs_mntpt_inode_operations;
+                       inode->i_fop    = &afs_mntpt_file_operations;
+               } else {
+                       inode->i_mode   = S_IFLNK | vnode->status.mode;
+                       inode->i_op     = &page_symlink_inode_operations;
+               }
                inode_nohighmem(inode);
                break;
        default:
@@ -70,27 +83,15 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
 
        set_nlink(inode, vnode->status.nlink);
        inode->i_uid            = vnode->status.owner;
-       inode->i_gid            = GLOBAL_ROOT_GID;
+       inode->i_gid            = vnode->status.group;
        inode->i_size           = vnode->status.size;
-       inode->i_ctime.tv_sec   = vnode->status.mtime_server;
+       inode->i_ctime.tv_sec   = vnode->status.mtime_client;
        inode->i_ctime.tv_nsec  = 0;
        inode->i_atime          = inode->i_mtime = inode->i_ctime;
        inode->i_blocks         = 0;
        inode->i_generation     = vnode->fid.unique;
        inode->i_version        = vnode->status.data_version;
        inode->i_mapping->a_ops = &afs_fs_aops;
-
-       /* check to see whether a symbolic link is really a mountpoint */
-       if (vnode->status.type == AFS_FTYPE_SYMLINK) {
-               afs_mntpt_check_symlink(vnode, key);
-
-               if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) {
-                       inode->i_mode   = S_IFDIR | vnode->status.mode;
-                       inode->i_op     = &afs_mntpt_inode_operations;
-                       inode->i_fop    = &afs_mntpt_file_operations;
-               }
-       }
-
        return 0;
 }
 
@@ -245,12 +246,13 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
                        vnode->cb_version = 0;
                        vnode->cb_expiry = 0;
                        vnode->cb_type = 0;
-                       vnode->cb_expires = get_seconds();
+                       vnode->cb_expires = ktime_get_real_seconds();
                } else {
                        vnode->cb_version = cb->version;
                        vnode->cb_expiry = cb->expiry;
                        vnode->cb_type = cb->type;
-                       vnode->cb_expires = vnode->cb_expiry + get_seconds();
+                       vnode->cb_expires = vnode->cb_expiry +
+                               ktime_get_real_seconds();
                }
        }
 
@@ -323,7 +325,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
            !test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) &&
            !test_bit(AFS_VNODE_MODIFIED, &vnode->flags) &&
            !test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
-               if (vnode->cb_expires < get_seconds() + 10) {
+               if (vnode->cb_expires < ktime_get_real_seconds() + 10) {
                        _debug("callback expired");
                        set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
                } else {
@@ -444,7 +446,7 @@ void afs_evict_inode(struct inode *inode)
 
        mutex_lock(&vnode->permits_lock);
        permits = vnode->permits;
-       rcu_assign_pointer(vnode->permits, NULL);
+       RCU_INIT_POINTER(vnode->permits, NULL);
        mutex_unlock(&vnode->permits_lock);
        if (permits)
                call_rcu(&permits->rcu, afs_zap_permits);
index 5dfa56903a2d4b6ff058160ef973efaaa5e690d8..a6901360fb81d435bf47a85b781a89a1056fd900 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/compiler.h>
 #include <linux/kernel.h>
+#include <linux/ktime.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/rxrpc.h>
@@ -90,7 +91,10 @@ struct afs_call {
        unsigned                request_size;   /* size of request data */
        unsigned                reply_max;      /* maximum size of reply */
        unsigned                first_offset;   /* offset into mapping[first] */
-       unsigned                last_to;        /* amount of mapping[last] */
+       union {
+               unsigned        last_to;        /* amount of mapping[last] */
+               unsigned        count2;         /* count used in unmarshalling */
+       };
        unsigned char           unmarshall;     /* unmarshalling phase */
        bool                    incoming;       /* T if incoming call */
        bool                    send_pages;     /* T if data from mapping should be sent */
@@ -127,12 +131,11 @@ struct afs_call_type {
  */
 struct afs_read {
        loff_t                  pos;            /* Where to start reading */
-       loff_t                  len;            /* How much to read */
+       loff_t                  len;            /* How much we're asking for */
        loff_t                  actual_len;     /* How much we're actually getting */
+       loff_t                  remain;         /* Amount remaining */
        atomic_t                usage;
-       unsigned int            remain;         /* Amount remaining */
        unsigned int            index;          /* Which page we're reading into */
-       unsigned int            pg_offset;      /* Offset in page we're at */
        unsigned int            nr_pages;
        void (*page_done)(struct afs_call *, struct afs_read *);
        struct page             *pages[];
@@ -247,7 +250,7 @@ struct afs_cache_vhash {
  */
 struct afs_vlocation {
        atomic_t                usage;
-       time_t                  time_of_death;  /* time at which put reduced usage to 0 */
+       time64_t                time_of_death;  /* time at which put reduced usage to 0 */
        struct list_head        link;           /* link in cell volume location list */
        struct list_head        grave;          /* link in master graveyard list */
        struct list_head        update;         /* link in master update list */
@@ -258,7 +261,7 @@ struct afs_vlocation {
        struct afs_cache_vlocation vldb;        /* volume information DB record */
        struct afs_volume       *vols[3];       /* volume access record pointer (index by type) */
        wait_queue_head_t       waitq;          /* status change waitqueue */
-       time_t                  update_at;      /* time at which record should be updated */
+       time64_t                update_at;      /* time at which record should be updated */
        spinlock_t              lock;           /* access lock */
        afs_vlocation_state_t   state;          /* volume location state */
        unsigned short          upd_rej_cnt;    /* ENOMEDIUM count during update */
@@ -271,7 +274,7 @@ struct afs_vlocation {
  */
 struct afs_server {
        atomic_t                usage;
-       time_t                  time_of_death;  /* time at which put reduced usage to 0 */
+       time64_t                time_of_death;  /* time at which put reduced usage to 0 */
        struct in_addr          addr;           /* server address */
        struct afs_cell         *cell;          /* cell in which server resides */
        struct list_head        link;           /* link in cell's server list */
@@ -374,8 +377,8 @@ struct afs_vnode {
        struct rb_node          server_rb;      /* link in server->fs_vnodes */
        struct rb_node          cb_promise;     /* link in server->cb_promises */
        struct work_struct      cb_broken_work; /* work to be done on callback break */
-       time_t                  cb_expires;     /* time at which callback expires */
-       time_t                  cb_expires_at;  /* time used to order cb_promise */
+       time64_t                cb_expires;     /* time at which callback expires */
+       time64_t                cb_expires_at;  /* time used to order cb_promise */
        unsigned                cb_version;     /* callback version */
        unsigned                cb_expiry;      /* callback expiry time */
        afs_callback_type_t     cb_type;        /* type of callback */
@@ -557,7 +560,6 @@ extern const struct inode_operations afs_autocell_inode_operations;
 extern const struct file_operations afs_mntpt_file_operations;
 
 extern struct vfsmount *afs_d_automount(struct path *);
-extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
 extern void afs_mntpt_kill_timer(void);
 
 /*
@@ -718,6 +720,7 @@ extern int afs_writepages(struct address_space *, struct writeback_control *);
 extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
 extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *);
 extern int afs_writeback_all(struct afs_vnode *);
+extern int afs_flush(struct file *, fl_owner_t);
 extern int afs_fsync(struct file *, loff_t, loff_t, int);
 
 
index 91ea1aa0d8b3ab0a817b525e9f9b3deec98f775f..100b207efc9eaddff4ed9f7e0e4415ed62ba2880 100644 (file)
@@ -84,6 +84,8 @@ int afs_abort_to_error(u32 abort_code)
        case RXKADDATALEN:      return -EKEYREJECTED;
        case RXKADILLEGALLEVEL: return -EKEYREJECTED;
 
+       case RXGEN_OPCODE:      return -ENOTSUPP;
+
        default:                return -EREMOTEIO;
        }
 }
index d4fb0afc0097d4947d3c2013cf27f521b055d423..bd3b65cde282a24769f7c549c9fe52c85b6c8e4e 100644 (file)
@@ -46,59 +46,6 @@ static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
 
 static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
 
-/*
- * check a symbolic link to see whether it actually encodes a mountpoint
- * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately
- */
-int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
-{
-       struct page *page;
-       size_t size;
-       char *buf;
-       int ret;
-
-       _enter("{%x:%u,%u}",
-              vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
-
-       /* read the contents of the symlink into the pagecache */
-       page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0,
-                              afs_page_filler, key);
-       if (IS_ERR(page)) {
-               ret = PTR_ERR(page);
-               goto out;
-       }
-
-       ret = -EIO;
-       if (PageError(page))
-               goto out_free;
-
-       buf = kmap(page);
-
-       /* examine the symlink's contents */
-       size = vnode->status.size;
-       _debug("symlink to %*.*s", (int) size, (int) size, buf);
-
-       if (size > 2 &&
-           (buf[0] == '%' || buf[0] == '#') &&
-           buf[size - 1] == '.'
-           ) {
-               _debug("symlink is a mountpoint");
-               spin_lock(&vnode->lock);
-               set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
-               vnode->vfs_inode.i_flags |= S_AUTOMOUNT;
-               spin_unlock(&vnode->lock);
-       }
-
-       ret = 0;
-
-       kunmap(page);
-out_free:
-       put_page(page);
-out:
-       _leave(" = %d", ret);
-       return ret;
-}
-
 /*
  * no valid lookup procedure on this sort of dir
  */
index 419ef05dcb5ec7149a3a0b5de657c75bbc6eabb4..8f76b13d55494bddec9e81203c0734a0f6d811d7 100644 (file)
@@ -259,67 +259,74 @@ void afs_flat_call_destructor(struct afs_call *call)
        call->buffer = NULL;
 }
 
+#define AFS_BVEC_MAX 8
+
+/*
+ * Load the given bvec with the next few pages.
+ */
+static void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
+                         struct bio_vec *bv, pgoff_t first, pgoff_t last,
+                         unsigned offset)
+{
+       struct page *pages[AFS_BVEC_MAX];
+       unsigned int nr, n, i, to, bytes = 0;
+
+       nr = min_t(pgoff_t, last - first + 1, AFS_BVEC_MAX);
+       n = find_get_pages_contig(call->mapping, first, nr, pages);
+       ASSERTCMP(n, ==, nr);
+
+       msg->msg_flags |= MSG_MORE;
+       for (i = 0; i < nr; i++) {
+               to = PAGE_SIZE;
+               if (first + i >= last) {
+                       to = call->last_to;
+                       msg->msg_flags &= ~MSG_MORE;
+               }
+               bv[i].bv_page = pages[i];
+               bv[i].bv_len = to - offset;
+               bv[i].bv_offset = offset;
+               bytes += to - offset;
+               offset = 0;
+       }
+
+       iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC, bv, nr, bytes);
+}
+
 /*
  * attach the data from a bunch of pages on an inode to a call
  */
 static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
 {
-       struct page *pages[8];
-       unsigned count, n, loop, offset, to;
+       struct bio_vec bv[AFS_BVEC_MAX];
+       unsigned int bytes, nr, loop, offset;
        pgoff_t first = call->first, last = call->last;
        int ret;
 
-       _enter("");
-
        offset = call->first_offset;
        call->first_offset = 0;
 
        do {
-               _debug("attach %lx-%lx", first, last);
-
-               count = last - first + 1;
-               if (count > ARRAY_SIZE(pages))
-                       count = ARRAY_SIZE(pages);
-               n = find_get_pages_contig(call->mapping, first, count, pages);
-               ASSERTCMP(n, ==, count);
-
-               loop = 0;
-               do {
-                       struct bio_vec bvec = {.bv_page = pages[loop],
-                                              .bv_offset = offset};
-                       msg->msg_flags = 0;
-                       to = PAGE_SIZE;
-                       if (first + loop >= last)
-                               to = call->last_to;
-                       else
-                               msg->msg_flags = MSG_MORE;
-                       bvec.bv_len = to - offset;
-                       offset = 0;
-
-                       _debug("- range %u-%u%s",
-                              offset, to, msg->msg_flags ? " [more]" : "");
-                       iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC,
-                                     &bvec, 1, to - offset);
-
-                       /* have to change the state *before* sending the last
-                        * packet as RxRPC might give us the reply before it
-                        * returns from sending the request */
-                       if (first + loop >= last)
-                               call->state = AFS_CALL_AWAIT_REPLY;
-                       ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
-                                                    msg, to - offset);
-                       if (ret < 0)
-                               break;
-               } while (++loop < count);
-               first += count;
-
-               for (loop = 0; loop < count; loop++)
-                       put_page(pages[loop]);
+               afs_load_bvec(call, msg, bv, first, last, offset);
+               offset = 0;
+               bytes = msg->msg_iter.count;
+               nr = msg->msg_iter.nr_segs;
+
+               /* Have to change the state *before* sending the last
+                * packet as RxRPC might give us the reply before it
+                * returns from sending the request.
+                */
+               if (first + nr - 1 >= last)
+                       call->state = AFS_CALL_AWAIT_REPLY;
+               ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
+                                            msg, bytes);
+               for (loop = 0; loop < nr; loop++)
+                       put_page(bv[loop].bv_page);
                if (ret < 0)
                        break;
+
+               first += nr;
        } while (first <= last);
 
-       _leave(" = %d", ret);
        return ret;
 }
 
@@ -333,6 +340,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        struct rxrpc_call *rxcall;
        struct msghdr msg;
        struct kvec iov[1];
+       size_t offset;
+       u32 abort_code;
        int ret;
 
        _enter("%x,{%d},", addr->s_addr, ntohs(call->port));
@@ -381,9 +390,11 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        msg.msg_controllen      = 0;
        msg.msg_flags           = (call->send_pages ? MSG_MORE : 0);
 
-       /* have to change the state *before* sending the last packet as RxRPC
-        * might give us the reply before it returns from sending the
-        * request */
+       /* We have to change the state *before* sending the last packet as
+        * rxrpc might give us the reply before it returns from sending the
+        * request.  Further, if the send fails, we may already have been given
+        * a notification and may have collected it.
+        */
        if (!call->send_pages)
                call->state = AFS_CALL_AWAIT_REPLY;
        ret = rxrpc_kernel_send_data(afs_socket, rxcall,
@@ -405,7 +416,17 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        return afs_wait_for_call_to_complete(call);
 
 error_do_abort:
-       rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT, -ret, "KSD");
+       call->state = AFS_CALL_COMPLETE;
+       if (ret != -ECONNABORTED) {
+               rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT,
+                                       -ret, "KSD");
+       } else {
+               abort_code = 0;
+               offset = 0;
+               rxrpc_kernel_recv_data(afs_socket, rxcall, NULL, 0, &offset,
+                                      false, &abort_code);
+               ret = call->type->abort_to_error(abort_code);
+       }
 error_kill_call:
        afs_put_call(call);
        _leave(" = %d", ret);
@@ -452,16 +473,18 @@ static void afs_deliver_to_call(struct afs_call *call)
                case -EINPROGRESS:
                case -EAGAIN:
                        goto out;
+               case -ECONNABORTED:
+                       goto call_complete;
                case -ENOTCONN:
                        abort_code = RX_CALL_DEAD;
                        rxrpc_kernel_abort_call(afs_socket, call->rxcall,
                                                abort_code, -ret, "KNC");
-                       goto do_abort;
+                       goto save_error;
                case -ENOTSUPP:
-                       abort_code = RX_INVALID_OPERATION;
+                       abort_code = RXGEN_OPCODE;
                        rxrpc_kernel_abort_call(afs_socket, call->rxcall,
                                                abort_code, -ret, "KIV");
-                       goto do_abort;
+                       goto save_error;
                case -ENODATA:
                case -EBADMSG:
                case -EMSGSIZE:
@@ -471,7 +494,7 @@ static void afs_deliver_to_call(struct afs_call *call)
                                abort_code = RXGEN_SS_UNMARSHAL;
                        rxrpc_kernel_abort_call(afs_socket, call->rxcall,
                                                abort_code, EBADMSG, "KUM");
-                       goto do_abort;
+                       goto save_error;
                }
        }
 
@@ -482,8 +505,9 @@ out:
        _leave("");
        return;
 
-do_abort:
+save_error:
        call->error = ret;
+call_complete:
        call->state = AFS_CALL_COMPLETE;
        goto done;
 }
@@ -493,7 +517,6 @@ do_abort:
  */
 static int afs_wait_for_call_to_complete(struct afs_call *call)
 {
-       const char *abort_why;
        int ret;
 
        DECLARE_WAITQUEUE(myself, current);
@@ -512,13 +535,8 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
                        continue;
                }
 
-               abort_why = "KWC";
-               ret = call->error;
-               if (call->state == AFS_CALL_COMPLETE)
-                       break;
-               abort_why = "KWI";
-               ret = -EINTR;
-               if (signal_pending(current))
+               if (call->state == AFS_CALL_COMPLETE ||
+                   signal_pending(current))
                        break;
                schedule();
        }
@@ -526,13 +544,14 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
        remove_wait_queue(&call->waitq, &myself);
        __set_current_state(TASK_RUNNING);
 
-       /* kill the call */
+       /* Kill off the call if it's still live. */
        if (call->state < AFS_CALL_COMPLETE) {
-               _debug("call incomplete");
+               _debug("call interrupted");
                rxrpc_kernel_abort_call(afs_socket, call->rxcall,
-                                       RX_CALL_DEAD, -ret, abort_why);
+                                       RX_USER_ABORT, -EINTR, "KWI");
        }
 
+       ret = call->error;
        _debug("call complete");
        afs_put_call(call);
        _leave(" = %d", ret);
index 8d010422dc8962b72fb3af64f75fdedb8e892cc0..ecb86a6701801cb74745bc99b74f9d8a367a2792 100644 (file)
@@ -114,7 +114,7 @@ void afs_clear_permits(struct afs_vnode *vnode)
 
        mutex_lock(&vnode->permits_lock);
        permits = vnode->permits;
-       rcu_assign_pointer(vnode->permits, NULL);
+       RCU_INIT_POINTER(vnode->permits, NULL);
        mutex_unlock(&vnode->permits_lock);
 
        if (permits)
@@ -340,17 +340,22 @@ int afs_permission(struct inode *inode, int mask)
        } else {
                if (!(access & AFS_ACE_LOOKUP))
                        goto permission_denied;
+               if ((mask & MAY_EXEC) && !(inode->i_mode & S_IXUSR))
+                       goto permission_denied;
                if (mask & (MAY_EXEC | MAY_READ)) {
                        if (!(access & AFS_ACE_READ))
                                goto permission_denied;
+                       if (!(inode->i_mode & S_IRUSR))
+                               goto permission_denied;
                } else if (mask & MAY_WRITE) {
                        if (!(access & AFS_ACE_WRITE))
                                goto permission_denied;
+                       if (!(inode->i_mode & S_IWUSR))
+                               goto permission_denied;
                }
        }
 
        key_put(key);
-       ret = generic_permission(inode, mask);
        _leave(" = %d", ret);
        return ret;
 
index d4066ab7dd5505b364a6506a1a2d932274bb5d9d..c001b1f2455fbf6dee4c9635c95590ada3890483 100644 (file)
@@ -242,7 +242,7 @@ void afs_put_server(struct afs_server *server)
        spin_lock(&afs_server_graveyard_lock);
        if (atomic_read(&server->usage) == 0) {
                list_move_tail(&server->grave, &afs_server_graveyard);
-               server->time_of_death = get_seconds();
+               server->time_of_death = ktime_get_real_seconds();
                queue_delayed_work(afs_wq, &afs_server_reaper,
                                   afs_server_timeout * HZ);
        }
@@ -277,9 +277,9 @@ static void afs_reap_server(struct work_struct *work)
        LIST_HEAD(corpses);
        struct afs_server *server;
        unsigned long delay, expiry;
-       time_t now;
+       time64_t now;
 
-       now = get_seconds();
+       now = ktime_get_real_seconds();
        spin_lock(&afs_server_graveyard_lock);
 
        while (!list_empty(&afs_server_graveyard)) {
index d7d8dd8c0b3187e6fe7eaed8e6300cb06826ff81..37b7c3b342a6b5a1f2f0cd06c0538e8e1d7f9073 100644 (file)
@@ -340,7 +340,8 @@ static void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
        struct afs_vlocation *xvl;
 
        /* wait at least 10 minutes before updating... */
-       vl->update_at = get_seconds() + afs_vlocation_update_timeout;
+       vl->update_at = ktime_get_real_seconds() +
+                       afs_vlocation_update_timeout;
 
        spin_lock(&afs_vlocation_updates_lock);
 
@@ -506,7 +507,7 @@ void afs_put_vlocation(struct afs_vlocation *vl)
        if (atomic_read(&vl->usage) == 0) {
                _debug("buried");
                list_move_tail(&vl->grave, &afs_vlocation_graveyard);
-               vl->time_of_death = get_seconds();
+               vl->time_of_death = ktime_get_real_seconds();
                queue_delayed_work(afs_wq, &afs_vlocation_reap,
                                   afs_vlocation_timeout * HZ);
 
@@ -543,11 +544,11 @@ static void afs_vlocation_reaper(struct work_struct *work)
        LIST_HEAD(corpses);
        struct afs_vlocation *vl;
        unsigned long delay, expiry;
-       time_t now;
+       time64_t now;
 
        _enter("");
 
-       now = get_seconds();
+       now = ktime_get_real_seconds();
        spin_lock(&afs_vlocation_graveyard_lock);
 
        while (!list_empty(&afs_vlocation_graveyard)) {
@@ -622,13 +623,13 @@ static void afs_vlocation_updater(struct work_struct *work)
 {
        struct afs_cache_vlocation vldb;
        struct afs_vlocation *vl, *xvl;
-       time_t now;
+       time64_t now;
        long timeout;
        int ret;
 
        _enter("");
 
-       now = get_seconds();
+       now = ktime_get_real_seconds();
 
        /* find a record to update */
        spin_lock(&afs_vlocation_updates_lock);
@@ -684,7 +685,8 @@ static void afs_vlocation_updater(struct work_struct *work)
 
        /* and then reschedule */
        _debug("reschedule");
-       vl->update_at = get_seconds() + afs_vlocation_update_timeout;
+       vl->update_at = ktime_get_real_seconds() +
+                       afs_vlocation_update_timeout;
 
        spin_lock(&afs_vlocation_updates_lock);
 
index c83c1a0e851fb34051c026bcea8e2a561299cf95..2d2fccd5044bcd9b02127246824c1221ec502484 100644 (file)
@@ -84,10 +84,9 @@ void afs_put_writeback(struct afs_writeback *wb)
  * partly or wholly fill a page that's under preparation for writing
  */
 static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
-                        loff_t pos, struct page *page)
+                        loff_t pos, unsigned int len, struct page *page)
 {
        struct afs_read *req;
-       loff_t i_size;
        int ret;
 
        _enter(",,%llu", (unsigned long long)pos);
@@ -99,14 +98,10 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
 
        atomic_set(&req->usage, 1);
        req->pos = pos;
+       req->len = len;
        req->nr_pages = 1;
        req->pages[0] = page;
-
-       i_size = i_size_read(&vnode->vfs_inode);
-       if (pos + PAGE_SIZE > i_size)
-               req->len = i_size - pos;
-       else
-               req->len = PAGE_SIZE;
+       get_page(page);
 
        ret = afs_vnode_fetch_data(vnode, key, req);
        afs_put_read(req);
@@ -159,12 +154,12 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
                kfree(candidate);
                return -ENOMEM;
        }
-       *pagep = page;
-       /* page won't leak in error case: it eventually gets cleaned off LRU */
 
        if (!PageUptodate(page) && len != PAGE_SIZE) {
-               ret = afs_fill_page(vnode, key, index << PAGE_SHIFT, page);
+               ret = afs_fill_page(vnode, key, pos & PAGE_MASK, PAGE_SIZE, page);
                if (ret < 0) {
+                       unlock_page(page);
+                       put_page(page);
                        kfree(candidate);
                        _leave(" = %d [prep]", ret);
                        return ret;
@@ -172,6 +167,9 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
                SetPageUptodate(page);
        }
 
+       /* page won't leak in error case: it eventually gets cleaned off LRU */
+       *pagep = page;
+
 try_again:
        spin_lock(&vnode->writeback_lock);
 
@@ -233,7 +231,7 @@ flush_conflicting_wb:
        if (wb->state == AFS_WBACK_PENDING)
                wb->state = AFS_WBACK_CONFLICTING;
        spin_unlock(&vnode->writeback_lock);
-       if (PageDirty(page)) {
+       if (clear_page_dirty_for_io(page)) {
                ret = afs_write_back_from_locked_page(wb, page);
                if (ret < 0) {
                        afs_put_writeback(candidate);
@@ -257,7 +255,9 @@ int afs_write_end(struct file *file, struct address_space *mapping,
                  struct page *page, void *fsdata)
 {
        struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
+       struct key *key = file->private_data;
        loff_t i_size, maybe_i_size;
+       int ret;
 
        _enter("{%x:%u},{%lx}",
               vnode->fid.vid, vnode->fid.vnode, page->index);
@@ -273,6 +273,20 @@ int afs_write_end(struct file *file, struct address_space *mapping,
                spin_unlock(&vnode->writeback_lock);
        }
 
+       if (!PageUptodate(page)) {
+               if (copied < len) {
+                       /* Try and load any missing data from the server.  The
+                        * unmarshalling routine will take care of clearing any
+                        * bits that are beyond the EOF.
+                        */
+                       ret = afs_fill_page(vnode, key, pos + copied,
+                                           len - copied, page);
+                       if (ret < 0)
+                               return ret;
+               }
+               SetPageUptodate(page);
+       }
+
        set_page_dirty(page);
        if (PageDirty(page))
                _debug("dirtied");
@@ -307,10 +321,14 @@ static void afs_kill_pages(struct afs_vnode *vnode, bool error,
                ASSERTCMP(pv.nr, ==, count);
 
                for (loop = 0; loop < count; loop++) {
-                       ClearPageUptodate(pv.pages[loop]);
+                       struct page *page = pv.pages[loop];
+                       ClearPageUptodate(page);
                        if (error)
-                               SetPageError(pv.pages[loop]);
-                       end_page_writeback(pv.pages[loop]);
+                               SetPageError(page);
+                       if (PageWriteback(page))
+                               end_page_writeback(page);
+                       if (page->index >= first)
+                               first = page->index + 1;
                }
 
                __pagevec_release(&pv);
@@ -335,8 +353,6 @@ static int afs_write_back_from_locked_page(struct afs_writeback *wb,
        _enter(",%lx", primary_page->index);
 
        count = 1;
-       if (!clear_page_dirty_for_io(primary_page))
-               BUG();
        if (test_set_page_writeback(primary_page))
                BUG();
 
@@ -502,17 +518,17 @@ static int afs_writepages_region(struct address_space *mapping,
                 */
                lock_page(page);
 
-               if (page->mapping != mapping) {
+               if (page->mapping != mapping || !PageDirty(page)) {
                        unlock_page(page);
                        put_page(page);
                        continue;
                }
 
-               if (wbc->sync_mode != WB_SYNC_NONE)
-                       wait_on_page_writeback(page);
-
-               if (PageWriteback(page) || !PageDirty(page)) {
+               if (PageWriteback(page)) {
                        unlock_page(page);
+                       if (wbc->sync_mode != WB_SYNC_NONE)
+                               wait_on_page_writeback(page);
+                       put_page(page);
                        continue;
                }
 
@@ -523,6 +539,8 @@ static int afs_writepages_region(struct address_space *mapping,
                wb->state = AFS_WBACK_WRITING;
                spin_unlock(&wb->vnode->writeback_lock);
 
+               if (!clear_page_dirty_for_io(page))
+                       BUG();
                ret = afs_write_back_from_locked_page(wb, page);
                unlock_page(page);
                put_page(page);
@@ -745,6 +763,20 @@ out:
        return ret;
 }
 
+/*
+ * Flush out all outstanding writes on a file opened for writing when it is
+ * closed.
+ */
+int afs_flush(struct file *file, fl_owner_t id)
+{
+       _enter("");
+
+       if ((file->f_mode & FMODE_WRITE) == 0)
+               return 0;
+
+       return vfs_fsync(file, 0);
+}
+
 /*
  * notification that a previously read-only page is about to become writable
  * - if it returns an error, the caller will deliver a bus error signal
index 28e81922a21c1ecead950f50cf3e685ad03c57f6..8df797432740df92e9c35c67fa75ce0331c193ff 100644 (file)
@@ -1714,7 +1714,8 @@ static int __process_pages_contig(struct address_space *mapping,
                         * can we find nothing at @index.
                         */
                        ASSERT(page_ops & PAGE_LOCK);
-                       return ret;
+                       err = -EAGAIN;
+                       goto out;
                }
 
                for (i = 0; i < ret; i++) {
index c40060cc481f60440044d00ea4a76904cc4d9761..2315039356529fac0315a57733a035d86a00b3b1 100644 (file)
@@ -6709,6 +6709,20 @@ static noinline int uncompress_inline(struct btrfs_path *path,
        max_size = min_t(unsigned long, PAGE_SIZE, max_size);
        ret = btrfs_decompress(compress_type, tmp, page,
                               extent_offset, inline_size, max_size);
+
+       /*
+        * decompression code contains a memset to fill in any space between the end
+        * of the uncompressed data and the end of max_size in case the decompressed
+        * data ends up shorter than ram_bytes.  That doesn't cover the hole between
+        * the end of an inline extent and the beginning of the next block, so we
+        * cover that region here.
+        */
+
+       if (max_size + pg_offset < PAGE_SIZE) {
+               char *map = kmap(page);
+               memset(map + pg_offset + max_size, 0, PAGE_SIZE - max_size - pg_offset);
+               kunmap(page);
+       }
        kfree(tmp);
        return ret;
 }
index 02a7a9286449d467741d64e8e817bb2902309926..6d6eca394d4d4107b8459b828b563acbbc9f082e 100644 (file)
@@ -327,7 +327,6 @@ EXPORT_SYMBOL(fscrypt_decrypt_page);
 static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *dir;
-       struct fscrypt_info *ci;
        int dir_has_key, cached_with_key;
 
        if (flags & LOOKUP_RCU)
@@ -339,18 +338,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
                return 0;
        }
 
-       ci = d_inode(dir)->i_crypt_info;
-       if (ci && ci->ci_keyring_key &&
-           (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-                                         (1 << KEY_FLAG_REVOKED) |
-                                         (1 << KEY_FLAG_DEAD))))
-               ci = NULL;
-
        /* this should eventually be an flag in d_flags */
        spin_lock(&dentry->d_lock);
        cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
        spin_unlock(&dentry->d_lock);
-       dir_has_key = (ci != NULL);
+       dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
        dput(dir);
 
        /*
index 13052b85c3930f071be764c5fbbeb091429002d3..37b49894c762344841117b2a0042c5e9ec8b7140 100644 (file)
@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
                fname->disk_name.len = iname->len;
                return 0;
        }
-       ret = fscrypt_get_crypt_info(dir);
+       ret = fscrypt_get_encryption_info(dir);
        if (ret && ret != -EOPNOTSUPP)
                return ret;
 
index fdbb8af32eafdb6bae492658d376abf15f8a3d69..e39696e644942a80d110035e2d49570840823af7 100644 (file)
@@ -67,7 +67,6 @@ struct fscrypt_info {
        u8 ci_filename_mode;
        u8 ci_flags;
        struct crypto_skcipher *ci_ctfm;
-       struct key *ci_keyring_key;
        u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
 };
 
@@ -101,7 +100,4 @@ extern int fscrypt_do_page_crypto(const struct inode *inode,
 extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
                                              gfp_t gfp_flags);
 
-/* keyinfo.c */
-extern int fscrypt_get_crypt_info(struct inode *);
-
 #endif /* _FSCRYPT_PRIVATE_H */
index d5d896fa5a71675272131d797919924b2398a85a..8cdfddce2b34868f0cfe3f71da55d64187172a38 100644 (file)
@@ -95,6 +95,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
        kfree(description);
        if (IS_ERR(keyring_key))
                return PTR_ERR(keyring_key);
+       down_read(&keyring_key->sem);
 
        if (keyring_key->type != &key_type_logon) {
                printk_once(KERN_WARNING
@@ -102,11 +103,9 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
                res = -ENOKEY;
                goto out;
        }
-       down_read(&keyring_key->sem);
        ukp = user_key_payload_locked(keyring_key);
        if (ukp->datalen != sizeof(struct fscrypt_key)) {
                res = -EINVAL;
-               up_read(&keyring_key->sem);
                goto out;
        }
        master_key = (struct fscrypt_key *)ukp->data;
@@ -117,17 +116,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
                                "%s: key size incorrect: %d\n",
                                __func__, master_key->size);
                res = -ENOKEY;
-               up_read(&keyring_key->sem);
                goto out;
        }
        res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
-       up_read(&keyring_key->sem);
-       if (res)
-               goto out;
-
-       crypt_info->ci_keyring_key = keyring_key;
-       return 0;
 out:
+       up_read(&keyring_key->sem);
        key_put(keyring_key);
        return res;
 }
@@ -169,12 +162,11 @@ static void put_crypt_info(struct fscrypt_info *ci)
        if (!ci)
                return;
 
-       key_put(ci->ci_keyring_key);
        crypto_free_skcipher(ci->ci_ctfm);
        kmem_cache_free(fscrypt_info_cachep, ci);
 }
 
-int fscrypt_get_crypt_info(struct inode *inode)
+int fscrypt_get_encryption_info(struct inode *inode)
 {
        struct fscrypt_info *crypt_info;
        struct fscrypt_context ctx;
@@ -184,21 +176,15 @@ int fscrypt_get_crypt_info(struct inode *inode)
        u8 *raw_key = NULL;
        int res;
 
+       if (inode->i_crypt_info)
+               return 0;
+
        res = fscrypt_initialize(inode->i_sb->s_cop->flags);
        if (res)
                return res;
 
        if (!inode->i_sb->s_cop->get_context)
                return -EOPNOTSUPP;
-retry:
-       crypt_info = ACCESS_ONCE(inode->i_crypt_info);
-       if (crypt_info) {
-               if (!crypt_info->ci_keyring_key ||
-                               key_validate(crypt_info->ci_keyring_key) == 0)
-                       return 0;
-               fscrypt_put_encryption_info(inode, crypt_info);
-               goto retry;
-       }
 
        res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
        if (res < 0) {
@@ -229,7 +215,6 @@ retry:
        crypt_info->ci_data_mode = ctx.contents_encryption_mode;
        crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
        crypt_info->ci_ctfm = NULL;
-       crypt_info->ci_keyring_key = NULL;
        memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
                                sizeof(crypt_info->ci_master_key));
 
@@ -273,14 +258,8 @@ retry:
        if (res)
                goto out;
 
-       kzfree(raw_key);
-       raw_key = NULL;
-       if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
-               put_crypt_info(crypt_info);
-               goto retry;
-       }
-       return 0;
-
+       if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
+               crypt_info = NULL;
 out:
        if (res == -ENOKEY)
                res = 0;
@@ -288,6 +267,7 @@ out:
        kzfree(raw_key);
        return res;
 }
+EXPORT_SYMBOL(fscrypt_get_encryption_info);
 
 void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
 {
@@ -305,17 +285,3 @@ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
        put_crypt_info(ci);
 }
 EXPORT_SYMBOL(fscrypt_put_encryption_info);
-
-int fscrypt_get_encryption_info(struct inode *inode)
-{
-       struct fscrypt_info *ci = inode->i_crypt_info;
-
-       if (!ci ||
-               (ci->ci_keyring_key &&
-                (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-                                              (1 << KEY_FLAG_REVOKED) |
-                                              (1 << KEY_FLAG_DEAD)))))
-               return fscrypt_get_crypt_info(inode);
-       return 0;
-}
-EXPORT_SYMBOL(fscrypt_get_encryption_info);
index 14b76da71269487f22b941f82dbf01d6adea07c7..4908906d54d562263093cd5245fcb14e36d18b8e 100644 (file)
@@ -33,17 +33,10 @@ static int create_encryption_context_from_policy(struct inode *inode,
                                const struct fscrypt_policy *policy)
 {
        struct fscrypt_context ctx;
-       int res;
 
        if (!inode->i_sb->s_cop->set_context)
                return -EOPNOTSUPP;
 
-       if (inode->i_sb->s_cop->prepare_context) {
-               res = inode->i_sb->s_cop->prepare_context(inode);
-               if (res)
-                       return res;
-       }
-
        ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
        memcpy(ctx.master_key_descriptor, policy->master_key_descriptor,
                                        FS_KEY_DESCRIPTOR_SIZE);
index 7d398d300e972c3604727ac8d6d4fbf7302318a6..9382db998ec9549319f47b55ccd561abf1169874 100644 (file)
@@ -743,7 +743,7 @@ static int tcp_accept_from_sock(struct connection *con)
        newsock->type = con->sock->type;
        newsock->ops = con->sock->ops;
 
-       result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK);
+       result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK, true);
        if (result < 0)
                goto accept_err;
 
index 30a9f210d1e32c8a01635821b2937407d5b21773..375fb1c05d49ce87a287213720ca0ebf5e0deef1 100644 (file)
@@ -1169,10 +1169,9 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
        set_buffer_uptodate(dir_block);
        err = ext4_handle_dirty_dirent_node(handle, inode, dir_block);
        if (err)
-               goto out;
+               return err;
        set_buffer_verified(dir_block);
-out:
-       return err;
+       return ext4_mark_inode_dirty(handle, inode);
 }
 
 static int ext4_convert_inline_data_nolock(handle_t *handle,
index 7385e6a6b6cb549041d098a565c36c20794f7f14..4247d8d25687814dd1b844ea5555feeb43854d99 100644 (file)
@@ -5400,7 +5400,7 @@ int ext4_getattr(const struct path *path, struct kstat *stat,
         * If there is inline data in the inode, the inode will normally not
         * have data blocks allocated (it may have an external xattr block).
         * Report at least one sector for such files, so tools like tar, rsync,
-        * others doen't incorrectly think the file is completely sparse.
+        * others don't incorrectly think the file is completely sparse.
         */
        if (unlikely(ext4_has_inline_data(inode)))
                stat->blocks += (stat->size + 511) >> 9;
index 578f8c33fb44ad34062e978277f5def1d8aeebe1..c992ef2c2f94c0865d14de67e2c5b99857edf71f 100644 (file)
@@ -511,7 +511,7 @@ mext_check_arguments(struct inode *orig_inode,
        if ((orig_start & ~(PAGE_MASK >> orig_inode->i_blkbits)) !=
            (donor_start & ~(PAGE_MASK >> orig_inode->i_blkbits))) {
                ext4_debug("ext4 move extent: orig and donor's start "
-                       "offset are not alligned [ino:orig %lu, donor %lu]\n",
+                       "offsets are not aligned [ino:orig %lu, donor %lu]\n",
                        orig_inode->i_ino, donor_inode->i_ino);
                return -EINVAL;
        }
index 2e03a0a88d92f7731346a26cbdc934458549660f..a9448db1cf7e87c2bd41daac6fbab7729bc87ecc 100644 (file)
@@ -1120,17 +1120,16 @@ static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
                                 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
 }
 
-static int ext4_prepare_context(struct inode *inode)
-{
-       return ext4_convert_inline_data(inode);
-}
-
 static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
                                                        void *fs_data)
 {
        handle_t *handle = fs_data;
        int res, res2, retries = 0;
 
+       res = ext4_convert_inline_data(inode);
+       if (res)
+               return res;
+
        /*
         * If a journal handle was specified, then the encryption context is
         * being set on a new inode via inheritance and is part of a larger
@@ -1196,7 +1195,6 @@ static unsigned ext4_max_namelen(struct inode *inode)
 static const struct fscrypt_operations ext4_cryptops = {
        .key_prefix             = "ext4:",
        .get_context            = ext4_get_context,
-       .prepare_context        = ext4_prepare_context,
        .set_context            = ext4_set_context,
        .dummy_context          = ext4_dummy_context,
        .is_encrypted           = ext4_encrypted_inode,
index 67636acf762475e211a641f4720e862ba886a40a..996e7900d4c8ea2d16f65f47e3f1082552b2fc66 100644 (file)
@@ -131,31 +131,26 @@ static __le32 ext4_xattr_block_csum(struct inode *inode,
 }
 
 static int ext4_xattr_block_csum_verify(struct inode *inode,
-                                       sector_t block_nr,
-                                       struct ext4_xattr_header *hdr)
+                                       struct buffer_head *bh)
 {
-       if (ext4_has_metadata_csum(inode->i_sb) &&
-           (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr)))
-               return 0;
-       return 1;
-}
-
-static void ext4_xattr_block_csum_set(struct inode *inode,
-                                     sector_t block_nr,
-                                     struct ext4_xattr_header *hdr)
-{
-       if (!ext4_has_metadata_csum(inode->i_sb))
-               return;
+       struct ext4_xattr_header *hdr = BHDR(bh);
+       int ret = 1;
 
-       hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr);
+       if (ext4_has_metadata_csum(inode->i_sb)) {
+               lock_buffer(bh);
+               ret = (hdr->h_checksum == ext4_xattr_block_csum(inode,
+                                                       bh->b_blocknr, hdr));
+               unlock_buffer(bh);
+       }
+       return ret;
 }
 
-static inline int ext4_handle_dirty_xattr_block(handle_t *handle,
-                                               struct inode *inode,
-                                               struct buffer_head *bh)
+static void ext4_xattr_block_csum_set(struct inode *inode,
+                                     struct buffer_head *bh)
 {
-       ext4_xattr_block_csum_set(inode, bh->b_blocknr, BHDR(bh));
-       return ext4_handle_dirty_metadata(handle, inode, bh);
+       if (ext4_has_metadata_csum(inode->i_sb))
+               BHDR(bh)->h_checksum = ext4_xattr_block_csum(inode,
+                                               bh->b_blocknr, BHDR(bh));
 }
 
 static inline const struct xattr_handler *
@@ -233,7 +228,7 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
        if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
            BHDR(bh)->h_blocks != cpu_to_le32(1))
                return -EFSCORRUPTED;
-       if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
+       if (!ext4_xattr_block_csum_verify(inode, bh))
                return -EFSBADCRC;
        error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size,
                                       bh->b_data);
@@ -618,23 +613,22 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
                        }
                }
 
+               ext4_xattr_block_csum_set(inode, bh);
                /*
                 * Beware of this ugliness: Releasing of xattr block references
                 * from different inodes can race and so we have to protect
                 * from a race where someone else frees the block (and releases
                 * its journal_head) before we are done dirtying the buffer. In
                 * nojournal mode this race is harmless and we actually cannot
-                * call ext4_handle_dirty_xattr_block() with locked buffer as
+                * call ext4_handle_dirty_metadata() with locked buffer as
                 * that function can call sync_dirty_buffer() so for that case
                 * we handle the dirtying after unlocking the buffer.
                 */
                if (ext4_handle_valid(handle))
-                       error = ext4_handle_dirty_xattr_block(handle, inode,
-                                                             bh);
+                       error = ext4_handle_dirty_metadata(handle, inode, bh);
                unlock_buffer(bh);
                if (!ext4_handle_valid(handle))
-                       error = ext4_handle_dirty_xattr_block(handle, inode,
-                                                             bh);
+                       error = ext4_handle_dirty_metadata(handle, inode, bh);
                if (IS_SYNC(inode))
                        ext4_handle_sync(handle);
                dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
@@ -863,13 +857,14 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
                                ext4_xattr_cache_insert(ext4_mb_cache,
                                        bs->bh);
                        }
+                       ext4_xattr_block_csum_set(inode, bs->bh);
                        unlock_buffer(bs->bh);
                        if (error == -EFSCORRUPTED)
                                goto bad_block;
                        if (!error)
-                               error = ext4_handle_dirty_xattr_block(handle,
-                                                                     inode,
-                                                                     bs->bh);
+                               error = ext4_handle_dirty_metadata(handle,
+                                                                  inode,
+                                                                  bs->bh);
                        if (error)
                                goto cleanup;
                        goto inserted;
@@ -967,10 +962,11 @@ inserted:
                                        ce->e_reusable = 0;
                                ea_bdebug(new_bh, "reusing; refcount now=%d",
                                          ref);
+                               ext4_xattr_block_csum_set(inode, new_bh);
                                unlock_buffer(new_bh);
-                               error = ext4_handle_dirty_xattr_block(handle,
-                                                                     inode,
-                                                                     new_bh);
+                               error = ext4_handle_dirty_metadata(handle,
+                                                                  inode,
+                                                                  new_bh);
                                if (error)
                                        goto cleanup_dquot;
                        }
@@ -1020,11 +1016,12 @@ getblk_failed:
                                goto getblk_failed;
                        }
                        memcpy(new_bh->b_data, s->base, new_bh->b_size);
+                       ext4_xattr_block_csum_set(inode, new_bh);
                        set_buffer_uptodate(new_bh);
                        unlock_buffer(new_bh);
                        ext4_xattr_cache_insert(ext4_mb_cache, new_bh);
-                       error = ext4_handle_dirty_xattr_block(handle,
-                                                             inode, new_bh);
+                       error = ext4_handle_dirty_metadata(handle, inode,
+                                                          new_bh);
                        if (error)
                                goto cleanup;
                }
index a77df377e2e8197097912c9248948c7e729ce566..ee2d0a485fc3478fc5f93b5b85c6dad0431e8ea0 100644 (file)
@@ -196,6 +196,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
        si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS);
        si->base_mem += NM_I(sbi)->nat_blocks * NAT_ENTRY_BITMAP_SIZE;
        si->base_mem += NM_I(sbi)->nat_blocks / 8;
+       si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
 
 get_cache:
        si->cache_mem = 0;
index 4650c9b85de77679adaa275406512868671bb1bb..8d5c62b07b283f53e90ded2366c8bb9375409fa2 100644 (file)
@@ -750,7 +750,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
        dentry_blk = page_address(page);
        bit_pos = dentry - dentry_blk->dentry;
        for (i = 0; i < slots; i++)
-               clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+               __clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
 
        /* Let's check and deallocate this dentry page */
        bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
index e849f83d611407b8968bec904c10f1939c40b4f1..0a6e115562f62edca5b60ee4c833e889a904c202 100644 (file)
@@ -561,6 +561,8 @@ struct f2fs_nm_info {
        struct mutex build_lock;        /* lock for build free nids */
        unsigned char (*free_nid_bitmap)[NAT_ENTRY_BITMAP_SIZE];
        unsigned char *nat_block_bitmap;
+       unsigned short *free_nid_count; /* free nid count of NAT block */
+       spinlock_t free_nid_lock;       /* protect updating of nid count */
 
        /* for checkpoint */
        char *nat_bitmap;               /* NAT bitmap pointer */
index 94967171dee87a381655ede9190ff0f66b3ca4af..481aa8dc79f46f4c156cf67cca665e8160e36e6a 100644 (file)
@@ -338,9 +338,6 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
                set_nat_flag(e, IS_CHECKPOINTED, false);
        __set_nat_cache_dirty(nm_i, e);
 
-       if (enabled_nat_bits(sbi, NULL) && new_blkaddr == NEW_ADDR)
-               clear_bit_le(NAT_BLOCK_OFFSET(ni->nid), nm_i->empty_nat_bits);
-
        /* update fsync_mark if its inode nat entry is still alive */
        if (ni->nid != ni->ino)
                e = __lookup_nat_cache(nm_i, ni->ino);
@@ -1823,7 +1820,8 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid)
                kmem_cache_free(free_nid_slab, i);
 }
 
-void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, bool set)
+static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
+                       bool set, bool build, bool locked)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
        unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid);
@@ -1833,9 +1831,18 @@ void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, bool set)
                return;
 
        if (set)
-               set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
+               __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
        else
-               clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
+               __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
+
+       if (!locked)
+               spin_lock(&nm_i->free_nid_lock);
+       if (set)
+               nm_i->free_nid_count[nat_ofs]++;
+       else if (!build)
+               nm_i->free_nid_count[nat_ofs]--;
+       if (!locked)
+               spin_unlock(&nm_i->free_nid_lock);
 }
 
 static void scan_nat_page(struct f2fs_sb_info *sbi,
@@ -1847,7 +1854,10 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
        unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid);
        int i;
 
-       set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
+       if (test_bit_le(nat_ofs, nm_i->nat_block_bitmap))
+               return;
+
+       __set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
 
        i = start_nid % NAT_ENTRY_PER_BLOCK;
 
@@ -1861,7 +1871,7 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
                f2fs_bug_on(sbi, blk_addr == NEW_ADDR);
                if (blk_addr == NULL_ADDR)
                        freed = add_free_nid(sbi, start_nid, true);
-               update_free_nid_bitmap(sbi, start_nid, freed);
+               update_free_nid_bitmap(sbi, start_nid, freed, true, false);
        }
 }
 
@@ -1877,6 +1887,8 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi)
        for (i = 0; i < nm_i->nat_blocks; i++) {
                if (!test_bit_le(i, nm_i->nat_block_bitmap))
                        continue;
+               if (!nm_i->free_nid_count[i])
+                       continue;
                for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) {
                        nid_t nid;
 
@@ -1907,58 +1919,6 @@ out:
        up_read(&nm_i->nat_tree_lock);
 }
 
-static int scan_nat_bits(struct f2fs_sb_info *sbi)
-{
-       struct f2fs_nm_info *nm_i = NM_I(sbi);
-       struct page *page;
-       unsigned int i = 0;
-       nid_t nid;
-
-       if (!enabled_nat_bits(sbi, NULL))
-               return -EAGAIN;
-
-       down_read(&nm_i->nat_tree_lock);
-check_empty:
-       i = find_next_bit_le(nm_i->empty_nat_bits, nm_i->nat_blocks, i);
-       if (i >= nm_i->nat_blocks) {
-               i = 0;
-               goto check_partial;
-       }
-
-       for (nid = i * NAT_ENTRY_PER_BLOCK; nid < (i + 1) * NAT_ENTRY_PER_BLOCK;
-                                                                       nid++) {
-               if (unlikely(nid >= nm_i->max_nid))
-                       break;
-               add_free_nid(sbi, nid, true);
-       }
-
-       if (nm_i->nid_cnt[FREE_NID_LIST] >= MAX_FREE_NIDS)
-               goto out;
-       i++;
-       goto check_empty;
-
-check_partial:
-       i = find_next_zero_bit_le(nm_i->full_nat_bits, nm_i->nat_blocks, i);
-       if (i >= nm_i->nat_blocks) {
-               disable_nat_bits(sbi, true);
-               up_read(&nm_i->nat_tree_lock);
-               return -EINVAL;
-       }
-
-       nid = i * NAT_ENTRY_PER_BLOCK;
-       page = get_current_nat_page(sbi, nid);
-       scan_nat_page(sbi, page, nid);
-       f2fs_put_page(page, 1);
-
-       if (nm_i->nid_cnt[FREE_NID_LIST] < MAX_FREE_NIDS) {
-               i++;
-               goto check_partial;
-       }
-out:
-       up_read(&nm_i->nat_tree_lock);
-       return 0;
-}
-
 static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -1980,21 +1940,6 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
 
                if (nm_i->nid_cnt[FREE_NID_LIST])
                        return;
-
-               /* try to find free nids with nat_bits */
-               if (!scan_nat_bits(sbi) && nm_i->nid_cnt[FREE_NID_LIST])
-                       return;
-       }
-
-       /* find next valid candidate */
-       if (enabled_nat_bits(sbi, NULL)) {
-               int idx = find_next_zero_bit_le(nm_i->full_nat_bits,
-                                       nm_i->nat_blocks, 0);
-
-               if (idx >= nm_i->nat_blocks)
-                       set_sbi_flag(sbi, SBI_NEED_FSCK);
-               else
-                       nid = idx * NAT_ENTRY_PER_BLOCK;
        }
 
        /* readahead nat pages to be scanned */
@@ -2081,7 +2026,7 @@ retry:
                __insert_nid_to_list(sbi, i, ALLOC_NID_LIST, false);
                nm_i->available_nids--;
 
-               update_free_nid_bitmap(sbi, *nid, false);
+               update_free_nid_bitmap(sbi, *nid, false, false, false);
 
                spin_unlock(&nm_i->nid_list_lock);
                return true;
@@ -2137,7 +2082,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
 
        nm_i->available_nids++;
 
-       update_free_nid_bitmap(sbi, nid, true);
+       update_free_nid_bitmap(sbi, nid, true, false, false);
 
        spin_unlock(&nm_i->nid_list_lock);
 
@@ -2383,7 +2328,7 @@ add_out:
        list_add_tail(&nes->set_list, head);
 }
 
-void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
+static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
                                                struct page *page)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -2402,16 +2347,16 @@ void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
                        valid++;
        }
        if (valid == 0) {
-               set_bit_le(nat_index, nm_i->empty_nat_bits);
-               clear_bit_le(nat_index, nm_i->full_nat_bits);
+               __set_bit_le(nat_index, nm_i->empty_nat_bits);
+               __clear_bit_le(nat_index, nm_i->full_nat_bits);
                return;
        }
 
-       clear_bit_le(nat_index, nm_i->empty_nat_bits);
+       __clear_bit_le(nat_index, nm_i->empty_nat_bits);
        if (valid == NAT_ENTRY_PER_BLOCK)
-               set_bit_le(nat_index, nm_i->full_nat_bits);
+               __set_bit_le(nat_index, nm_i->full_nat_bits);
        else
-               clear_bit_le(nat_index, nm_i->full_nat_bits);
+               __clear_bit_le(nat_index, nm_i->full_nat_bits);
 }
 
 static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
@@ -2467,11 +2412,11 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
                        add_free_nid(sbi, nid, false);
                        spin_lock(&NM_I(sbi)->nid_list_lock);
                        NM_I(sbi)->available_nids++;
-                       update_free_nid_bitmap(sbi, nid, true);
+                       update_free_nid_bitmap(sbi, nid, true, false, false);
                        spin_unlock(&NM_I(sbi)->nid_list_lock);
                } else {
                        spin_lock(&NM_I(sbi)->nid_list_lock);
-                       update_free_nid_bitmap(sbi, nid, false);
+                       update_free_nid_bitmap(sbi, nid, false, false, false);
                        spin_unlock(&NM_I(sbi)->nid_list_lock);
                }
        }
@@ -2577,6 +2522,40 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
        return 0;
 }
 
+inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       unsigned int i = 0;
+       nid_t nid, last_nid;
+
+       if (!enabled_nat_bits(sbi, NULL))
+               return;
+
+       for (i = 0; i < nm_i->nat_blocks; i++) {
+               i = find_next_bit_le(nm_i->empty_nat_bits, nm_i->nat_blocks, i);
+               if (i >= nm_i->nat_blocks)
+                       break;
+
+               __set_bit_le(i, nm_i->nat_block_bitmap);
+
+               nid = i * NAT_ENTRY_PER_BLOCK;
+               last_nid = (i + 1) * NAT_ENTRY_PER_BLOCK;
+
+               spin_lock(&nm_i->free_nid_lock);
+               for (; nid < last_nid; nid++)
+                       update_free_nid_bitmap(sbi, nid, true, true, true);
+               spin_unlock(&nm_i->free_nid_lock);
+       }
+
+       for (i = 0; i < nm_i->nat_blocks; i++) {
+               i = find_next_bit_le(nm_i->full_nat_bits, nm_i->nat_blocks, i);
+               if (i >= nm_i->nat_blocks)
+                       break;
+
+               __set_bit_le(i, nm_i->nat_block_bitmap);
+       }
+}
+
 static int init_node_manager(struct f2fs_sb_info *sbi)
 {
        struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
@@ -2638,7 +2617,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
        return 0;
 }
 
-int init_free_nid_cache(struct f2fs_sb_info *sbi)
+static int init_free_nid_cache(struct f2fs_sb_info *sbi)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
 
@@ -2651,6 +2630,14 @@ int init_free_nid_cache(struct f2fs_sb_info *sbi)
                                                                GFP_KERNEL);
        if (!nm_i->nat_block_bitmap)
                return -ENOMEM;
+
+       nm_i->free_nid_count = f2fs_kvzalloc(nm_i->nat_blocks *
+                                       sizeof(unsigned short), GFP_KERNEL);
+       if (!nm_i->free_nid_count)
+               return -ENOMEM;
+
+       spin_lock_init(&nm_i->free_nid_lock);
+
        return 0;
 }
 
@@ -2670,6 +2657,9 @@ int build_node_manager(struct f2fs_sb_info *sbi)
        if (err)
                return err;
 
+       /* load free nid status from nat_bits table */
+       load_free_nid_bitmap(sbi);
+
        build_free_nids(sbi, true, true);
        return 0;
 }
@@ -2730,6 +2720,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
 
        kvfree(nm_i->nat_block_bitmap);
        kvfree(nm_i->free_nid_bitmap);
+       kvfree(nm_i->free_nid_count);
 
        kfree(nm_i->nat_bitmap);
        kfree(nm_i->nat_bits);
index 4bd7a8b19332d176d78b0a40c24e7bb12bbe2f5e..29ef7088c5582a480b6a1f7965fbbcca4f07e24e 100644 (file)
@@ -1163,6 +1163,12 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
                if (f2fs_discard_en(sbi) &&
                        !f2fs_test_and_set_bit(offset, se->discard_map))
                        sbi->discard_blks--;
+
+               /* don't overwrite by SSR to keep node chain */
+               if (se->type == CURSEG_WARM_NODE) {
+                       if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map))
+                               se->ckpt_valid_blocks++;
+               }
        } else {
                if (!f2fs_test_and_clear_bit(offset, se->cur_valid_map)) {
 #ifdef CONFIG_F2FS_CHECK_FS
index ef600591d96f9a42be98699025f4cf94ef8e7762..63ee2940775ce9c16daca5c2f7590e0c6e57bc07 100644 (file)
@@ -173,19 +173,33 @@ static void wb_wakeup(struct bdi_writeback *wb)
        spin_unlock_bh(&wb->work_lock);
 }
 
+static void finish_writeback_work(struct bdi_writeback *wb,
+                                 struct wb_writeback_work *work)
+{
+       struct wb_completion *done = work->done;
+
+       if (work->auto_free)
+               kfree(work);
+       if (done && atomic_dec_and_test(&done->cnt))
+               wake_up_all(&wb->bdi->wb_waitq);
+}
+
 static void wb_queue_work(struct bdi_writeback *wb,
                          struct wb_writeback_work *work)
 {
        trace_writeback_queue(wb, work);
 
-       spin_lock_bh(&wb->work_lock);
-       if (!test_bit(WB_registered, &wb->state))
-               goto out_unlock;
        if (work->done)
                atomic_inc(&work->done->cnt);
-       list_add_tail(&work->list, &wb->work_list);
-       mod_delayed_work(bdi_wq, &wb->dwork, 0);
-out_unlock:
+
+       spin_lock_bh(&wb->work_lock);
+
+       if (test_bit(WB_registered, &wb->state)) {
+               list_add_tail(&work->list, &wb->work_list);
+               mod_delayed_work(bdi_wq, &wb->dwork, 0);
+       } else
+               finish_writeback_work(wb, work);
+
        spin_unlock_bh(&wb->work_lock);
 }
 
@@ -1873,16 +1887,9 @@ static long wb_do_writeback(struct bdi_writeback *wb)
 
        set_bit(WB_writeback_running, &wb->state);
        while ((work = get_next_work_item(wb)) != NULL) {
-               struct wb_completion *done = work->done;
-
                trace_writeback_exec(wb, work);
-
                wrote += wb_writeback(wb, work);
-
-               if (work->auto_free)
-                       kfree(work);
-               if (done && atomic_dec_and_test(&done->cnt))
-                       wake_up_all(&wb->bdi->wb_waitq);
+               finish_writeback_work(wb, work);
        }
 
        /*
index c45084ac642d1929058ea5d903ad796d574a45cc..511e1ed7e2ded7b0a9dc9882cffe0b66c37c96a2 100644 (file)
@@ -207,7 +207,7 @@ struct lm_lockname {
        struct gfs2_sbd *ln_sbd;
        u64 ln_number;
        unsigned int ln_type;
-};
+} __packed __aligned(sizeof(int));
 
 #define lm_name_equal(name1, name2) \
         (((name1)->ln_number == (name2)->ln_number) && \
index a1a359bfcc9cd4ff84254e464788ab3031dfe90f..5adc2fb62b0fab89899e5d0acba1e8019a73c766 100644 (file)
@@ -1125,10 +1125,8 @@ static journal_t *journal_init_common(struct block_device *bdev,
 
        /* Set up a default-sized revoke table for the new mount. */
        err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);
-       if (err) {
-               kfree(journal);
-               return NULL;
-       }
+       if (err)
+               goto err_cleanup;
 
        spin_lock_init(&journal->j_history_lock);
 
@@ -1145,23 +1143,25 @@ static journal_t *journal_init_common(struct block_device *bdev,
        journal->j_wbufsize = n;
        journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *),
                                        GFP_KERNEL);
-       if (!journal->j_wbuf) {
-               kfree(journal);
-               return NULL;
-       }
+       if (!journal->j_wbuf)
+               goto err_cleanup;
 
        bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize);
        if (!bh) {
                pr_err("%s: Cannot get buffer for journal superblock\n",
                        __func__);
-               kfree(journal->j_wbuf);
-               kfree(journal);
-               return NULL;
+               goto err_cleanup;
        }
        journal->j_sb_buffer = bh;
        journal->j_superblock = (journal_superblock_t *)bh->b_data;
 
        return journal;
+
+err_cleanup:
+       kfree(journal->j_wbuf);
+       jbd2_journal_destroy_revoke(journal);
+       kfree(journal);
+       return NULL;
 }
 
 /* jbd2_journal_init_dev and jbd2_journal_init_inode:
index cfc38b5521189f8ff64330ff33aa6ac8c25794ec..f9aefcda585418abcc37e58226eb39f3ac883172 100644 (file)
@@ -280,6 +280,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
 
 fail1:
        jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
+       journal->j_revoke_table[0] = NULL;
 fail0:
        return -ENOMEM;
 }
index bb79972dc638ba8bf27beef1930deeb186820af5..773774531aff5fc081610706ea39756b0e5a5c25 100644 (file)
@@ -232,12 +232,12 @@ static struct svc_serv_ops nfs41_cb_sv_ops = {
        .svo_module             = THIS_MODULE,
 };
 
-struct svc_serv_ops *nfs4_cb_sv_ops[] = {
+static struct svc_serv_ops *nfs4_cb_sv_ops[] = {
        [0] = &nfs40_cb_sv_ops,
        [1] = &nfs41_cb_sv_ops,
 };
 #else
-struct svc_serv_ops *nfs4_cb_sv_ops[] = {
+static struct svc_serv_ops *nfs4_cb_sv_ops[] = {
        [0] = &nfs40_cb_sv_ops,
        [1] = NULL,
 };
index 91a8d610ba0fa6db7cc76458ec2514aec9b124db..390ada8741bcbfd2e4aaecb3f759ec0707003674 100644 (file)
@@ -325,10 +325,33 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
        return NULL;
 }
 
-static bool nfs_client_init_is_complete(const struct nfs_client *clp)
+/*
+ * Return true if @clp is done initializing, false if still working on it.
+ *
+ * Use nfs_client_init_status to check if it was successful.
+ */
+bool nfs_client_init_is_complete(const struct nfs_client *clp)
 {
        return clp->cl_cons_state <= NFS_CS_READY;
 }
+EXPORT_SYMBOL_GPL(nfs_client_init_is_complete);
+
+/*
+ * Return 0 if @clp was successfully initialized, -errno otherwise.
+ *
+ * This must be called *after* nfs_client_init_is_complete() returns true,
+ * otherwise it will pop WARN_ON_ONCE and return -EINVAL
+ */
+int nfs_client_init_status(const struct nfs_client *clp)
+{
+       /* called without checking nfs_client_init_is_complete */
+       if (clp->cl_cons_state > NFS_CS_READY) {
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+       return clp->cl_cons_state;
+}
+EXPORT_SYMBOL_GPL(nfs_client_init_status);
 
 int nfs_wait_client_init_complete(const struct nfs_client *clp)
 {
index f956ca20a8a3595e36e6cae0e913dc90a47b1e22..d913e818858f3fee8d7d5c199714d2d79b1bef39 100644 (file)
@@ -266,6 +266,7 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
        struct nfs4_pnfs_ds *ret = ds;
        struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
+       int status;
 
        if (ds == NULL) {
                printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
@@ -277,9 +278,14 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
        if (ds->ds_clp)
                goto out_test_devid;
 
-       nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
+       status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
                             dataserver_retrans, 4,
                             s->nfs_client->cl_minorversion);
+       if (status) {
+               nfs4_mark_deviceid_unavailable(devid);
+               ret = NULL;
+               goto out;
+       }
 
 out_test_devid:
        if (ret->ds_clp == NULL ||
index f4f39b0ab09b25170ed1f9f9a9a961ecadb9a5d2..98b34c9b0564b348615a0d560b863c11cd17ad5e 100644 (file)
@@ -175,7 +175,19 @@ ff_layout_no_read_on_rw(struct pnfs_layout_segment *lseg)
 static inline bool
 ff_layout_test_devid_unavailable(struct nfs4_deviceid_node *node)
 {
-       return nfs4_test_deviceid_unavailable(node);
+       /*
+        * Flexfiles should never mark a DS unavailable, but if it does
+        * print a (ratelimited) warning as this can affect performance.
+        */
+       if (nfs4_test_deviceid_unavailable(node)) {
+               u32 *p = (u32 *)node->deviceid.data;
+
+               pr_warn_ratelimited("NFS: flexfiles layout referencing an "
+                               "unavailable device [%x%x%x%x]\n",
+                               p[0], p[1], p[2], p[3]);
+               return true;
+       }
+       return false;
 }
 
 static inline int
index e5a6f248697b369003e89ed526608d7cd2a296eb..85fde93dff774e7edf619bffe43657b9c2346034 100644 (file)
@@ -384,6 +384,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
        struct inode *ino = lseg->pls_layout->plh_inode;
        struct nfs_server *s = NFS_SERVER(ino);
        unsigned int max_payload;
+       int status;
 
        if (!ff_layout_mirror_valid(lseg, mirror, true)) {
                pr_err_ratelimited("NFS: %s: No data server for offset index %d\n",
@@ -404,7 +405,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
        /* FIXME: For now we assume the server sent only one version of NFS
         * to use for the DS.
         */
-       nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
+       status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
                             dataserver_retrans,
                             mirror->mirror_ds->ds_versions[0].version,
                             mirror->mirror_ds->ds_versions[0].minor_version);
@@ -420,11 +421,11 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
                        mirror->mirror_ds->ds_versions[0].wsize = max_payload;
                goto out;
        }
+out_fail:
        ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
                                 mirror, lseg->pls_range.offset,
                                 lseg->pls_range.length, NFS4ERR_NXIO,
                                 OP_ILLEGAL, GFP_NOIO);
-out_fail:
        if (fail_return || !ff_layout_has_available_ds(lseg))
                pnfs_error_mark_layout_for_return(ino, lseg);
        ds = NULL;
index 09ca5095c04e427c881785170aefe7fdf58e7621..7b38fedb7e032824ec509edca5cf465a22147851 100644 (file)
@@ -186,6 +186,8 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *,
                                           struct nfs_fh *,
                                           struct nfs_fattr *,
                                           rpc_authflavor_t);
+extern bool nfs_client_init_is_complete(const struct nfs_client *clp);
+extern int nfs_client_init_status(const struct nfs_client *clp);
 extern int nfs_wait_client_init_complete(const struct nfs_client *clp);
 extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
 extern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
index 5ae9d64ea08bc80c97c7c4c5b71ee73ef1a6ba8b..8346ccbf2d52e518b6fa61d0c8cbb3d033ec1f02 100644 (file)
@@ -1023,9 +1023,9 @@ static void nfs4_session_set_rwsize(struct nfs_server *server)
        server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
        server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
 
-       if (server->rsize > server_resp_sz)
+       if (!server->rsize || server->rsize > server_resp_sz)
                server->rsize = server_resp_sz;
-       if (server->wsize > server_rqst_sz)
+       if (!server->wsize || server->wsize > server_rqst_sz)
                server->wsize = server_rqst_sz;
 #endif /* CONFIG_NFS_V4_1 */
 }
index 1b183686c6d4f06c3b1d4ed044c527bff6ba4a83..c780d98035ccf79573c47ac8fb46b8f06a17653e 100644 (file)
@@ -2258,8 +2258,6 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
        if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
                return 0;
 
-       /* even though OPEN succeeded, access is denied. Close the file */
-       nfs4_close_state(state, fmode);
        return -EACCES;
 }
 
@@ -7427,11 +7425,11 @@ static void nfs4_exchange_id_release(void *data)
        struct nfs41_exchange_id_data *cdata =
                                        (struct nfs41_exchange_id_data *)data;
 
-       nfs_put_client(cdata->args.client);
        if (cdata->xprt) {
                xprt_put(cdata->xprt);
                rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
        }
+       nfs_put_client(cdata->args.client);
        kfree(cdata->res.impl_id);
        kfree(cdata->res.server_scope);
        kfree(cdata->res.server_owner);
@@ -7538,10 +7536,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
        task_setup_data.callback_data = calldata;
 
        task = rpc_run_task(&task_setup_data);
-       if (IS_ERR(task)) {
-       status = PTR_ERR(task);
-               goto out_impl_id;
-       }
+       if (IS_ERR(task))
+               return PTR_ERR(task);
 
        if (!xprt) {
                status = rpc_wait_for_completion_task(task);
@@ -7569,6 +7565,7 @@ out_server_owner:
        kfree(calldata->res.server_owner);
 out_calldata:
        kfree(calldata);
+       nfs_put_client(clp);
        goto out;
 }
 
index f0369e36275341404db0684aebb4e9bdba273205..80ce289eea05326336a7edecbe8a132ee4900d23 100644 (file)
@@ -3942,7 +3942,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
                if (len <= 0)
                        goto out;
                dprintk("%s: name=%s\n", __func__, group_name->data);
-               return NFS_ATTR_FATTR_OWNER_NAME;
+               return NFS_ATTR_FATTR_GROUP_NAME;
        } else {
                len = xdr_stream_decode_opaque_inline(xdr, (void **)&p,
                                XDR_MAX_NETOBJ);
index 63f77b49a586a53a1abbcf7b517aa2a90f3ddb2e..590e1e35781f0b737b5b277d76ab56092f8e3f3b 100644 (file)
@@ -367,7 +367,7 @@ void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds);
 struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs,
                                      gfp_t gfp_flags);
 void nfs4_pnfs_v3_ds_connect_unload(void);
-void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
+int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
                          struct nfs4_deviceid_node *devid, unsigned int timeo,
                          unsigned int retrans, u32 version, u32 minor_version);
 struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
index 9414b492439fbf0e70d32f9238ac29b8e9cf50be..7250b95549ecc73bd1dbdae9ec909aac64f93a49 100644 (file)
@@ -745,15 +745,17 @@ out:
 /*
  * Create an rpc connection to the nfs4_pnfs_ds data server.
  * Currently only supports IPv4 and IPv6 addresses.
- * If connection fails, make devid unavailable.
+ * If connection fails, make devid unavailable and return a -errno.
  */
-void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
+int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
                          struct nfs4_deviceid_node *devid, unsigned int timeo,
                          unsigned int retrans, u32 version, u32 minor_version)
 {
-       if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
-               int err = 0;
+       int err;
 
+again:
+       err = 0;
+       if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
                if (version == 3) {
                        err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
                                                       retrans);
@@ -766,12 +768,29 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
                        err = -EPROTONOSUPPORT;
                }
 
-               if (err)
-                       nfs4_mark_deviceid_unavailable(devid);
                nfs4_clear_ds_conn_bit(ds);
        } else {
                nfs4_wait_ds_connect(ds);
+
+               /* what was waited on didn't connect AND didn't mark unavail */
+               if (!ds->ds_clp && !nfs4_test_deviceid_unavailable(devid))
+                       goto again;
        }
+
+       /*
+        * At this point the ds->ds_clp should be ready, but it might have
+        * hit an error.
+        */
+       if (!err) {
+               if (!ds->ds_clp || !nfs_client_init_is_complete(ds->ds_clp)) {
+                       WARN_ON_ONCE(ds->ds_clp ||
+                               !nfs4_test_deviceid_unavailable(devid));
+                       return -EINVAL;
+               }
+               err = nfs_client_init_status(ds->ds_clp);
+       }
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect);
 
index e75b056f46f43583b84da4a423cbafedb850c630..abb2c8a3be42e4755f747c62a1cec5466f13ee77 100644 (file)
@@ -1784,7 +1784,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                        (long long)req_offset(req));
                if (status < 0) {
                        nfs_context_set_write_error(req->wb_context, status);
-                       nfs_inode_remove_request(req);
+                       if (req->wb_page)
+                               nfs_inode_remove_request(req);
                        dprintk_cont(", error = %d\n", status);
                        goto next;
                }
@@ -1793,7 +1794,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                 * returned by the server against all stored verfs. */
                if (!nfs_write_verifier_cmp(&req->wb_verf, &data->verf.verifier)) {
                        /* We have a match */
-                       nfs_inode_remove_request(req);
+                       if (req->wb_page)
+                               nfs_inode_remove_request(req);
                        dprintk_cont(" OK\n");
                        goto next;
                }
index 4348027384f5edf06a66dd417214b9bbd3dd05cd..d0ab7e56d0b41a7a97f3640eb0ab4801f747dffc 100644 (file)
@@ -1863,7 +1863,7 @@ static int o2net_accept_one(struct socket *sock, int *more)
 
        new_sock->type = sock->type;
        new_sock->ops = sock->ops;
-       ret = sock->ops->accept(sock, new_sock, O_NONBLOCK);
+       ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, false);
        if (ret < 0)
                goto out;
 
index d04547fcf274af0eaee18096c94b22652551b9f7..eb00bc133bca673c556eb85a18385bbc3748dfcf 100644 (file)
@@ -125,6 +125,8 @@ extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
 extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
 extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
 extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
+extern int xfs_dir2_sf_verify(struct xfs_mount *mp, struct xfs_dir2_sf_hdr *sfp,
+               int size);
 
 /* xfs_dir2_readdir.c */
 extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx,
index c6809ff41197d934c068e84b19eb77986bc7dccf..96b45cd6c63f0686d3c1cce5c41b232f0ab82080 100644 (file)
@@ -629,6 +629,93 @@ xfs_dir2_sf_check(
 }
 #endif /* DEBUG */
 
+/* Verify the consistency of an inline directory. */
+int
+xfs_dir2_sf_verify(
+       struct xfs_mount                *mp,
+       struct xfs_dir2_sf_hdr          *sfp,
+       int                             size)
+{
+       struct xfs_dir2_sf_entry        *sfep;
+       struct xfs_dir2_sf_entry        *next_sfep;
+       char                            *endp;
+       const struct xfs_dir_ops        *dops;
+       xfs_ino_t                       ino;
+       int                             i;
+       int                             i8count;
+       int                             offset;
+       __uint8_t                       filetype;
+
+       dops = xfs_dir_get_ops(mp, NULL);
+
+       /*
+        * Give up if the directory is way too short.
+        */
+       XFS_WANT_CORRUPTED_RETURN(mp, size >
+                       offsetof(struct xfs_dir2_sf_hdr, parent));
+       XFS_WANT_CORRUPTED_RETURN(mp, size >=
+                       xfs_dir2_sf_hdr_size(sfp->i8count));
+
+       endp = (char *)sfp + size;
+
+       /* Check .. entry */
+       ino = dops->sf_get_parent_ino(sfp);
+       i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
+       XFS_WANT_CORRUPTED_RETURN(mp, !xfs_dir_ino_validate(mp, ino));
+       offset = dops->data_first_offset;
+
+       /* Check all reported entries */
+       sfep = xfs_dir2_sf_firstentry(sfp);
+       for (i = 0; i < sfp->count; i++) {
+               /*
+                * struct xfs_dir2_sf_entry has a variable length.
+                * Check the fixed-offset parts of the structure are
+                * within the data buffer.
+                */
+               XFS_WANT_CORRUPTED_RETURN(mp,
+                               ((char *)sfep + sizeof(*sfep)) < endp);
+
+               /* Don't allow names with known bad length. */
+               XFS_WANT_CORRUPTED_RETURN(mp, sfep->namelen > 0);
+               XFS_WANT_CORRUPTED_RETURN(mp, sfep->namelen < MAXNAMELEN);
+
+               /*
+                * Check that the variable-length part of the structure is
+                * within the data buffer.  The next entry starts after the
+                * name component, so nextentry is an acceptable test.
+                */
+               next_sfep = dops->sf_nextentry(sfp, sfep);
+               XFS_WANT_CORRUPTED_RETURN(mp, endp >= (char *)next_sfep);
+
+               /* Check that the offsets always increase. */
+               XFS_WANT_CORRUPTED_RETURN(mp,
+                               xfs_dir2_sf_get_offset(sfep) >= offset);
+
+               /* Check the inode number. */
+               ino = dops->sf_get_ino(sfp, sfep);
+               i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
+               XFS_WANT_CORRUPTED_RETURN(mp, !xfs_dir_ino_validate(mp, ino));
+
+               /* Check the file type. */
+               filetype = dops->sf_get_ftype(sfep);
+               XFS_WANT_CORRUPTED_RETURN(mp, filetype < XFS_DIR3_FT_MAX);
+
+               offset = xfs_dir2_sf_get_offset(sfep) +
+                               dops->data_entsize(sfep->namelen);
+
+               sfep = next_sfep;
+       }
+       XFS_WANT_CORRUPTED_RETURN(mp, i8count == sfp->i8count);
+       XFS_WANT_CORRUPTED_RETURN(mp, (void *)sfep == (void *)endp);
+
+       /* Make sure this whole thing ought to be in local format. */
+       XFS_WANT_CORRUPTED_RETURN(mp, offset +
+              (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
+              (uint)sizeof(xfs_dir2_block_tail_t) <= mp->m_dir_geo->blksize);
+
+       return 0;
+}
+
 /*
  * Create a new (shortform) directory.
  */
index 25c1e078aef6a5925c12f2cc91b0d18b8b38711b..9653e964eda4f99ca611bb2cb6449a470be45d48 100644 (file)
@@ -33,6 +33,8 @@
 #include "xfs_trace.h"
 #include "xfs_attr_sf.h"
 #include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_dir2_priv.h"
 
 kmem_zone_t *xfs_ifork_zone;
 
@@ -320,6 +322,7 @@ xfs_iformat_local(
        int             whichfork,
        int             size)
 {
+       int             error;
 
        /*
         * If the size is unreasonable, then something
@@ -336,6 +339,14 @@ xfs_iformat_local(
                return -EFSCORRUPTED;
        }
 
+       if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) {
+               error = xfs_dir2_sf_verify(ip->i_mount,
+                               (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip),
+                               size);
+               if (error)
+                       return error;
+       }
+
        xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
        return 0;
 }
@@ -856,7 +867,7 @@ xfs_iextents_copy(
  * In these cases, the format always takes precedence, because the
  * format indicates the current state of the fork.
  */
-void
+int
 xfs_iflush_fork(
        xfs_inode_t             *ip,
        xfs_dinode_t            *dip,
@@ -866,6 +877,7 @@ xfs_iflush_fork(
        char                    *cp;
        xfs_ifork_t             *ifp;
        xfs_mount_t             *mp;
+       int                     error;
        static const short      brootflag[2] =
                { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
        static const short      dataflag[2] =
@@ -874,7 +886,7 @@ xfs_iflush_fork(
                { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
 
        if (!iip)
-               return;
+               return 0;
        ifp = XFS_IFORK_PTR(ip, whichfork);
        /*
         * This can happen if we gave up in iformat in an error path,
@@ -882,12 +894,19 @@ xfs_iflush_fork(
         */
        if (!ifp) {
                ASSERT(whichfork == XFS_ATTR_FORK);
-               return;
+               return 0;
        }
        cp = XFS_DFORK_PTR(dip, whichfork);
        mp = ip->i_mount;
        switch (XFS_IFORK_FORMAT(ip, whichfork)) {
        case XFS_DINODE_FMT_LOCAL:
+               if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) {
+                       error = xfs_dir2_sf_verify(mp,
+                                       (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data,
+                                       ifp->if_bytes);
+                       if (error)
+                               return error;
+               }
                if ((iip->ili_fields & dataflag[whichfork]) &&
                    (ifp->if_bytes > 0)) {
                        ASSERT(ifp->if_u1.if_data != NULL);
@@ -940,6 +959,7 @@ xfs_iflush_fork(
                ASSERT(0);
                break;
        }
+       return 0;
 }
 
 /*
index 7fb8365326d1a745583c4f133bc5a63668316b33..132dc59fdde6942cd22fca4ae11b8adbc193f051 100644 (file)
@@ -140,7 +140,7 @@ typedef struct xfs_ifork {
 struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
 
 int            xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *);
-void           xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
+int            xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
                                struct xfs_inode_log_item *, int);
 void           xfs_idestroy_fork(struct xfs_inode *, int);
 void           xfs_idata_realloc(struct xfs_inode *, int, int);
index 003a99b83bd8845e22d6311be1d474679521242d..ad9396e516f6e389b88bca5dc2dc41d3372ed714 100644 (file)
@@ -71,22 +71,11 @@ xfs_dir2_sf_getdents(
        struct xfs_da_geometry  *geo = args->geo;
 
        ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
-       /*
-        * Give up if the directory is way too short.
-        */
-       if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
-               ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-               return -EIO;
-       }
-
        ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
        ASSERT(dp->i_df.if_u1.if_data != NULL);
 
        sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 
-       if (dp->i_d.di_size < xfs_dir2_sf_hdr_size(sfp->i8count))
-               return -EFSCORRUPTED;
-
        /*
         * If the block number in the offset is out of range, we're done.
         */
index 7eaf1ef74e3c63ebb3c640e32d2db87864984a4a..c7fe2c2123ab8375caf0e0349a454ed8b2762095 100644 (file)
@@ -3475,6 +3475,7 @@ xfs_iflush_int(
        struct xfs_inode_log_item *iip = ip->i_itemp;
        struct xfs_dinode       *dip;
        struct xfs_mount        *mp = ip->i_mount;
+       int                     error;
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        ASSERT(xfs_isiflocked(ip));
@@ -3557,9 +3558,14 @@ xfs_iflush_int(
        if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
                ip->i_d.di_flushiter = 0;
 
-       xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK);
-       if (XFS_IFORK_Q(ip))
-               xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK);
+       error = xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK);
+       if (error)
+               return error;
+       if (XFS_IFORK_Q(ip)) {
+               error = xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK);
+               if (error)
+                       return error;
+       }
        xfs_inobp_check(mp, bp);
 
        /*
index a2bfd7843f18f6e79d8bc7e5743b031345153053..e2b9c6fe271496e45dca5abb94d814dd8a9c3c04 100644 (file)
@@ -73,7 +73,7 @@ int af_alg_unregister_type(const struct af_alg_type *type);
 
 int af_alg_release(struct socket *sock);
 void af_alg_release_parent(struct sock *sk);
-int af_alg_accept(struct sock *sk, struct socket *newsock);
+int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern);
 
 int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len);
 void af_alg_free_sg(struct af_alg_sgl *sgl);
index 673acda012af44efe4fb5a7fc5279d08e416cc86..9b05886f9773cde8439a0c3e21b39ad29460c440 100644 (file)
@@ -287,18 +287,15 @@ static inline bool invalid_phys_cpuid(phys_cpuid_t phys_id)
 }
 
 /* Validate the processor object's proc_id */
-bool acpi_processor_validate_proc_id(int proc_id);
+bool acpi_duplicate_processor_id(int proc_id);
 
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 /* Arch dependent functions for cpu hotplug support */
 int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id,
                 int *pcpu);
 int acpi_unmap_cpu(int cpu);
-int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
-void acpi_set_processor_mapping(void);
-
 #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
 int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
 #endif
index c71dd8fa57640eab059ca21b2847609340b6b506..c41b8d99dd0e7f352bc8e57e4e2ffc4dd08c63b7 100644 (file)
@@ -556,7 +556,7 @@ enum ccp_engine {
  * struct ccp_cmd - CCP operation request
  * @entry: list element (ccp driver use only)
  * @work: work element used for callbacks (ccp driver use only)
- * @ccp: CCP device to be run on (ccp driver use only)
+ * @ccp: CCP device to be run on
  * @ret: operation return code (ccp driver use only)
  * @flags: cmd processing flags
  * @engine: CCP operation to perform
index 61d042bbbf607253033d9948b291cab2322814ba..68449293c4b6233c1a1d4133b1819376a9310225 100644 (file)
@@ -163,6 +163,7 @@ struct dccp_request_sock {
        __u64                    dreq_isr;
        __u64                    dreq_gsr;
        __be32                   dreq_service;
+       spinlock_t               dreq_lock;
        struct list_head         dreq_featneg;
        __u32                    dreq_timestamp_echo;
        __u32                    dreq_timestamp_time;
index 30c4570e928dfe871bc84382f14eb49b5cac018e..9ef518af5515a01e202dee3cf4c27ffcd8c56441 100644 (file)
@@ -1140,7 +1140,6 @@ static inline bool device_supports_offline(struct device *dev)
 extern void lock_device_hotplug(void);
 extern void unlock_device_hotplug(void);
 extern int lock_device_hotplug_sysfs(void);
-void assert_held_device_hotplug(void);
 extern int device_offline(struct device *dev);
 extern int device_online(struct device *dev);
 extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
index 9ca23fcfb5d73131b564ad81d887929abc0e954b..6fdfc884fdeb3d3cf81dcbd40c52c0b8c8d203b1 100644 (file)
@@ -20,6 +20,8 @@ struct sock_exterr_skb {
        struct sock_extended_err        ee;
        u16                             addr_offset;
        __be16                          port;
+       u8                              opt_stats:1,
+                                       unused:7;
 };
 
 #endif
index 0c167fdee5f7d126ed4de7e1201d514d1402a5ca..fbf7b39e81035506b73ddc860e3029119104b255 100644 (file)
@@ -409,6 +409,7 @@ struct bpf_prog {
        u16                     pages;          /* Number of allocated pages */
        kmemcheck_bitfield_begin(meta);
        u16                     jited:1,        /* Is our filter JIT'ed? */
+                               locked:1,       /* Program image locked? */
                                gpl_compatible:1, /* Is filter GPL compatible? */
                                cb_access:1,    /* Is control block accessed? */
                                dst_needed:1,   /* Do we need dst entry? */
@@ -554,22 +555,29 @@ static inline bool bpf_prog_was_classic(const struct bpf_prog *prog)
 #ifdef CONFIG_ARCH_HAS_SET_MEMORY
 static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
 {
-       set_memory_ro((unsigned long)fp, fp->pages);
+       fp->locked = 1;
+       WARN_ON_ONCE(set_memory_ro((unsigned long)fp, fp->pages));
 }
 
 static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
 {
-       set_memory_rw((unsigned long)fp, fp->pages);
+       if (fp->locked) {
+               WARN_ON_ONCE(set_memory_rw((unsigned long)fp, fp->pages));
+               /* In case set_memory_rw() fails, we want to be the first
+                * to crash here instead of some random place later on.
+                */
+               fp->locked = 0;
+       }
 }
 
 static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
 {
-       set_memory_ro((unsigned long)hdr, hdr->pages);
+       WARN_ON_ONCE(set_memory_ro((unsigned long)hdr, hdr->pages));
 }
 
 static inline void bpf_jit_binary_unlock_ro(struct bpf_binary_header *hdr)
 {
-       set_memory_rw((unsigned long)hdr, hdr->pages);
+       WARN_ON_ONCE(set_memory_rw((unsigned long)hdr, hdr->pages));
 }
 #else
 static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
index 547f81592ba134bce5d222a66405c782a91b80d8..10c1abfbac6c45d1049fdf9f1b1f133371521461 100644 (file)
@@ -87,7 +87,6 @@ struct fscrypt_operations {
        unsigned int flags;
        const char *key_prefix;
        int (*get_context)(struct inode *, void *, size_t);
-       int (*prepare_context)(struct inode *);
        int (*set_context)(struct inode *, const void *, size_t, void *);
        int (*dummy_context)(struct inode *);
        bool (*is_encrypted)(struct inode *);
index 2484b2fcc6eb58d0139605359fe97b285df8e5f5..933d936566055de430f9db64ae152eb31785b7ff 100644 (file)
@@ -143,15 +143,6 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
                                                struct fwnode_handle *child,
                                                enum gpiod_flags flags,
                                                const char *label);
-/* FIXME: delete this helper when users are switched over */
-static inline struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
-                         const char *con_id, struct fwnode_handle *child)
-{
-       return devm_fwnode_get_index_gpiod_from_child(dev, con_id,
-                                                     0, child,
-                                                     GPIOD_ASIS,
-                                                     "?");
-}
 
 #else /* CONFIG_GPIOLIB */
 
@@ -444,13 +435,6 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
        return ERR_PTR(-ENOSYS);
 }
 
-/* FIXME: delete this when all users are switched over */
-static inline struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
-                         const char *con_id, struct fwnode_handle *child)
-{
-       return ERR_PTR(-ENOSYS);
-}
-
 #endif /* CONFIG_GPIOLIB */
 
 static inline
index 78d59dba563e33e96f6658bfb764268e97f99573..88b6737491210aaf7a2ba66756672188992902ac 100644 (file)
@@ -88,6 +88,7 @@ enum hwmon_temp_attributes {
 #define HWMON_T_CRIT_HYST      BIT(hwmon_temp_crit_hyst)
 #define HWMON_T_EMERGENCY      BIT(hwmon_temp_emergency)
 #define HWMON_T_EMERGENCY_HYST BIT(hwmon_temp_emergency_hyst)
+#define HWMON_T_ALARM          BIT(hwmon_temp_alarm)
 #define HWMON_T_MIN_ALARM      BIT(hwmon_temp_min_alarm)
 #define HWMON_T_MAX_ALARM      BIT(hwmon_temp_max_alarm)
 #define HWMON_T_CRIT_ALARM     BIT(hwmon_temp_crit_alarm)
index 23ca41515527965239a56e92b909d53e75055cd4..fa7931933067982b2bac57f4c73aac039db8f692 100644 (file)
@@ -62,7 +62,7 @@ void iio_swd_group_init_type_name(struct iio_sw_device *d,
                                  const char *name,
                                  struct config_item_type *type)
 {
-#ifdef CONFIG_CONFIGFS_FS
+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
        config_group_init_type_name(&d->group, name, type);
 #endif
 }
index 6a6de187ddc0ff1e0e737f94261211b7ea4408e9..2e4de0deee531adbd7c1cd8ff1d25e0d0eb98d47 100644 (file)
@@ -125,9 +125,16 @@ enum iommu_attr {
 };
 
 /* These are the possible reserved region types */
-#define IOMMU_RESV_DIRECT      (1 << 0)
-#define IOMMU_RESV_RESERVED    (1 << 1)
-#define IOMMU_RESV_MSI         (1 << 2)
+enum iommu_resv_type {
+       /* Memory regions which must be mapped 1:1 at all times */
+       IOMMU_RESV_DIRECT,
+       /* Arbitrary "never map this or give it to a device" address ranges */
+       IOMMU_RESV_RESERVED,
+       /* Hardware MSI region (untranslated) */
+       IOMMU_RESV_MSI,
+       /* Software-managed MSI translation window */
+       IOMMU_RESV_SW_MSI,
+};
 
 /**
  * struct iommu_resv_region - descriptor for a reserved memory region
@@ -142,7 +149,7 @@ struct iommu_resv_region {
        phys_addr_t             start;
        size_t                  length;
        int                     prot;
-       int                     type;
+       enum iommu_resv_type    type;
 };
 
 #ifdef CONFIG_IOMMU_API
@@ -288,7 +295,8 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
 extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
 extern int iommu_request_dm_for_dev(struct device *dev);
 extern struct iommu_resv_region *
-iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type);
+iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot,
+                       enum iommu_resv_type type);
 extern int iommu_get_group_resv_regions(struct iommu_group *group,
                                        struct list_head *head);
 
index 1c823bef4c15105485bc0497a12708b8ee27ed9d..5734480c9590946412ebd16b7752c5341c4600be 100644 (file)
@@ -6,6 +6,7 @@
 struct kmem_cache;
 struct page;
 struct vm_struct;
+struct task_struct;
 
 #ifdef CONFIG_KASAN
 
index b01fe100908430708df0df5162594b497ffdad62..87ff4f58a2f0182ec0586c0dee923bc30e004149 100644 (file)
@@ -29,6 +29,11 @@ struct hlist_nulls_node {
        ((ptr)->first = (struct hlist_nulls_node *) NULLS_MARKER(nulls))
 
 #define hlist_nulls_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_nulls_entry_safe(ptr, type, member) \
+       ({ typeof(ptr) ____ptr = (ptr); \
+          !is_a_nulls(____ptr) ? hlist_nulls_entry(____ptr, type, member) : NULL; \
+       })
 /**
  * ptr_is_a_nulls - Test if a ptr is a nulls
  * @ptr: ptr to be tested
index 7e66e4f62858f395cd000226e9580785b03a4cf1..1beb1ec2fbdf339b34affc69508a5f5462b409b0 100644 (file)
@@ -476,6 +476,7 @@ enum {
 enum {
        MLX4_INTERFACE_STATE_UP         = 1 << 0,
        MLX4_INTERFACE_STATE_DELETION   = 1 << 1,
+       MLX4_INTERFACE_STATE_NOWAIT     = 1 << 2,
 };
 
 #define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \
index cd0c8bd0a1dec0d2047509177ee8d33de1f185d4..0620f5e18c96b706b70fb71005b29008a11fffb1 100644 (file)
@@ -146,7 +146,7 @@ struct proto_ops {
        int             (*socketpair)(struct socket *sock1,
                                      struct socket *sock2);
        int             (*accept)    (struct socket *sock,
-                                     struct socket *newsock, int flags);
+                                     struct socket *newsock, int flags, bool kern);
        int             (*getname)   (struct socket *sock,
                                      struct sockaddr *addr,
                                      int *sockaddr_len, int peer);
index 35d0fd7a4948e6e49eb7e75512461d935cccd161..fd0de00c0d777ed72cfab3fdbeb54e885c14be77 100644 (file)
@@ -76,22 +76,12 @@ struct gpmc_timings;
 struct omap_nand_platform_data;
 struct omap_onenand_platform_data;
 
-#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d,
-                         struct gpmc_timings *gpmc_t);
-#else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d,
-                                struct gpmc_timings *gpmc_t)
-{
-       return 0;
-}
-#endif
-
 #if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+extern int gpmc_onenand_init(struct omap_onenand_platform_data *d);
 #else
 #define board_onenand_data     NULL
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+static inline int gpmc_onenand_init(struct omap_onenand_platform_data *d)
 {
+       return 0;
 }
 #endif
index 772476028a6507f356fe3946372a024588679c3f..43a774873aa96d4af64d0cdebb579be572a6658a 100644 (file)
@@ -837,6 +837,10 @@ int genphy_read_status(struct phy_device *phydev);
 int genphy_suspend(struct phy_device *phydev);
 int genphy_resume(struct phy_device *phydev);
 int genphy_soft_reset(struct phy_device *phydev);
+static inline int genphy_no_soft_reset(struct phy_device *phydev)
+{
+       return 0;
+}
 void phy_driver_unregister(struct phy_driver *drv);
 void phy_drivers_unregister(struct phy_driver *drv, int n);
 int phy_driver_register(struct phy_driver *new_driver, struct module *owner);
index 4ae95f7e8597b0b43575d04aaf524cf252761e6e..a23a3315318048eec1fc18678e17967f03eaa89b 100644 (file)
@@ -156,5 +156,19 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
                ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \
                pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)))
 
+/**
+ * hlist_nulls_for_each_entry_safe -
+ *   iterate over list of given type safe against removal of list entry
+ * @tpos:      the type * to use as a loop cursor.
+ * @pos:       the &struct hlist_nulls_node to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the hlist_nulls_node within the struct.
+ */
+#define hlist_nulls_for_each_entry_safe(tpos, pos, head, member)               \
+       for (({barrier();}),                                                    \
+            pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));            \
+               (!is_a_nulls(pos)) &&                                           \
+               ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member);        \
+                  pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)); 1; });)
 #endif
 #endif
index 86b4ed75359e85345afb839483e5910bcf5fe6cb..96fb139bdd08fdec3ad83e689ad2808375473126 100644 (file)
@@ -31,31 +31,26 @@ static inline int device_reset_optional(struct device *dev)
 
 static inline int reset_control_reset(struct reset_control *rstc)
 {
-       WARN_ON(1);
        return 0;
 }
 
 static inline int reset_control_assert(struct reset_control *rstc)
 {
-       WARN_ON(1);
        return 0;
 }
 
 static inline int reset_control_deassert(struct reset_control *rstc)
 {
-       WARN_ON(1);
        return 0;
 }
 
 static inline int reset_control_status(struct reset_control *rstc)
 {
-       WARN_ON(1);
        return 0;
 }
 
 static inline void reset_control_put(struct reset_control *rstc)
 {
-       WARN_ON(1);
 }
 
 static inline int __must_check device_reset(struct device *dev)
@@ -74,14 +69,14 @@ static inline struct reset_control *__of_reset_control_get(
                                        const char *id, int index, bool shared,
                                        bool optional)
 {
-       return ERR_PTR(-ENOTSUPP);
+       return optional ? NULL : ERR_PTR(-ENOTSUPP);
 }
 
 static inline struct reset_control *__devm_reset_control_get(
                                        struct device *dev, const char *id,
                                        int index, bool shared, bool optional)
 {
-       return ERR_PTR(-ENOTSUPP);
+       return optional ? NULL : ERR_PTR(-ENOTSUPP);
 }
 
 #endif /* CONFIG_RESET_CONTROLLER */
index 1d0043dc34e427403a1c82458249bed83e87d3a0..de2a722fe3cf7c457352eb02548f0351a669ddf5 100644 (file)
 /* device can't handle Link Power Management */
 #define USB_QUIRK_NO_LPM                       BIT(10)
 
+/*
+ * Device reports its bInterval as linear frames instead of the
+ * USB 2.0 calculation.
+ */
+#define USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL  BIT(11)
+
 #endif /* __LINUX_USB_QUIRKS_H */
index 9638bfeb0d1f639ae310d1586b4e2fca567ba2f7..584f9a647ad4acca191ff6116a47c14da1385fa3 100644 (file)
@@ -48,6 +48,8 @@ struct virtio_vsock_pkt {
        struct virtio_vsock_hdr hdr;
        struct work_struct work;
        struct list_head list;
+       /* socket refcnt not held, only use for cancellation */
+       struct vsock_sock *vsk;
        void *buf;
        u32 len;
        u32 off;
@@ -56,6 +58,7 @@ struct virtio_vsock_pkt {
 
 struct virtio_vsock_pkt_info {
        u32 remote_cid, remote_port;
+       struct vsock_sock *vsk;
        struct msghdr *msg;
        u32 pkt_len;
        u16 type;
index f2758964ce6f890e3b11df5ba5bf2eefe636abd1..f32ed9ac181a47c00757596fc3b8c5733426c468 100644 (file)
@@ -100,6 +100,9 @@ struct vsock_transport {
        void (*destruct)(struct vsock_sock *);
        void (*release)(struct vsock_sock *);
 
+       /* Cancel all pending packets sent on vsock. */
+       int (*cancel_pkt)(struct vsock_sock *vsk);
+
        /* Connections. */
        int (*connect)(struct vsock_sock *);
 
index b7952d55b9c00039a9eca46544997c10722682b6..f39ae697347f6590459ee4178de84160b43841e2 100644 (file)
@@ -20,7 +20,8 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
                          int addr_len, int flags, int is_sendmsg);
 int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
                       int addr_len, int flags);
-int inet_accept(struct socket *sock, struct socket *newsock, int flags);
+int inet_accept(struct socket *sock, struct socket *newsock, int flags,
+               bool kern);
 int inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size);
 ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
                      size_t size, int flags);
index 826f198374f809a4b7ca23ada4a46433b972ef35..c7a577976bec0887218a969bc8197dc1c8eb13f0 100644 (file)
@@ -258,7 +258,7 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
         return (unsigned long)min_t(u64, when, max_when);
 }
 
-struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
+struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern);
 
 int inet_csk_get_port(struct sock *sk, unsigned short snum);
 
index f540f9ad2af4f673a204875864ce73f423204a74..19605878da4739d04f0642b20f8641ed8601d2eb 100644 (file)
@@ -244,7 +244,7 @@ extern s32 (*nf_ct_nat_offset)(const struct nf_conn *ct,
                               u32 seq);
 
 /* Fake conntrack entry for untracked connections */
-DECLARE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
+DECLARE_PER_CPU_ALIGNED(struct nf_conn, nf_conntrack_untracked);
 static inline struct nf_conn *nf_ct_untracked_get(void)
 {
        return raw_cpu_ptr(&nf_conntrack_untracked);
index 2aa8a9d80fbe8263a4b0e1c65f44e1ee2d9295d4..0136028652bdb8b3c20813b01b2fa8cfb16ba012 100644 (file)
@@ -103,6 +103,35 @@ struct nft_regs {
        };
 };
 
+/* Store/load an u16 or u8 integer to/from the u32 data register.
+ *
+ * Note, when using concatenations, register allocation happens at 32-bit
+ * level. So for store instruction, pad the rest part with zero to avoid
+ * garbage values.
+ */
+
+static inline void nft_reg_store16(u32 *dreg, u16 val)
+{
+       *dreg = 0;
+       *(u16 *)dreg = val;
+}
+
+static inline void nft_reg_store8(u32 *dreg, u8 val)
+{
+       *dreg = 0;
+       *(u8 *)dreg = val;
+}
+
+static inline u16 nft_reg_load16(u32 *sreg)
+{
+       return *(u16 *)sreg;
+}
+
+static inline u8 nft_reg_load8(u32 *sreg)
+{
+       return *(u8 *)sreg;
+}
+
 static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
                                 unsigned int len)
 {
@@ -203,7 +232,6 @@ struct nft_set_elem {
 struct nft_set;
 struct nft_set_iter {
        u8              genmask;
-       bool            flush;
        unsigned int    count;
        unsigned int    skip;
        int             err;
index d150b50662017378644c8f3ccf0218ecceaa2331..97983d1c05e4d327147110440f4a3925b13f6951 100644 (file)
@@ -9,12 +9,13 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
                     struct sk_buff *skb,
                     const struct nf_hook_state *state)
 {
+       unsigned int flags = IP6_FH_F_AUTH;
        int protohdr, thoff = 0;
        unsigned short frag_off;
 
        nft_set_pktinfo(pkt, skb, state);
 
-       protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
+       protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
        if (protohdr < 0) {
                nft_set_pktinfo_proto_unspec(pkt, skb);
                return;
@@ -32,6 +33,7 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
                                const struct nf_hook_state *state)
 {
 #if IS_ENABLED(CONFIG_IPV6)
+       unsigned int flags = IP6_FH_F_AUTH;
        struct ipv6hdr *ip6h, _ip6h;
        unsigned int thoff = 0;
        unsigned short frag_off;
@@ -50,7 +52,7 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
        if (pkt_len + sizeof(*ip6h) > skb->len)
                return -1;
 
-       protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
+       protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
        if (protohdr < 0)
                return -1;
 
index a244db5e5ff7fa65bcf0a4124cbbe5f4682e6d9d..592decebac752ffca16fddbc75cbf14f9283d125 100644 (file)
@@ -83,6 +83,7 @@ struct sctp_bind_addr;
 struct sctp_ulpq;
 struct sctp_ep_common;
 struct crypto_shash;
+struct sctp_stream;
 
 
 #include <net/sctp/tsnmap.h>
@@ -476,7 +477,8 @@ struct sctp_pf {
        int  (*send_verify) (struct sctp_sock *, union sctp_addr *);
        int  (*supported_addrs)(const struct sctp_sock *, __be16 *);
        struct sock *(*create_accept_sk) (struct sock *sk,
-                                         struct sctp_association *asoc);
+                                         struct sctp_association *asoc,
+                                         bool kern);
        int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr);
        void (*to_sk_saddr)(union sctp_addr *, struct sock *sk);
        void (*to_sk_daddr)(union sctp_addr *, struct sock *sk);
@@ -752,6 +754,8 @@ struct sctp_transport {
                /* Is the Path MTU update pending on this tranport */
                pmtu_pending:1,
 
+               dst_pending_confirm:1,  /* need to confirm neighbour */
+
                /* Has this transport moved the ctsn since we last sacked */
                sack_generation:1;
        u32 dst_cookie;
@@ -805,8 +809,6 @@ struct sctp_transport {
 
        __u32 burst_limited;    /* Holds old cwnd when max.burst is applied */
 
-       __u32 dst_pending_confirm;      /* need to confirm neighbour */
-
        /* Destination */
        struct dst_entry *dst;
        /* Source address. */
index 5e5997654db6454f82179cc35c4bc22e89d0c06f..03252d53975de7ad0da66d35802738830b0e3367 100644 (file)
@@ -236,6 +236,7 @@ struct sock_common {
   *    @sk_shutdown: mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
   *    @sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings
   *    @sk_lock:       synchronizer
+  *    @sk_kern_sock: True if sock is using kernel lock classes
   *    @sk_rcvbuf: size of receive buffer in bytes
   *    @sk_wq: sock wait queue and async head
   *    @sk_rx_dst: receive input route used by early demux
@@ -430,7 +431,8 @@ struct sock {
 #endif
 
        kmemcheck_bitfield_begin(flags);
-       unsigned int            sk_padding : 2,
+       unsigned int            sk_padding : 1,
+                               sk_kern_sock : 1,
                                sk_no_check_tx : 1,
                                sk_no_check_rx : 1,
                                sk_userlocks : 4,
@@ -1015,7 +1017,8 @@ struct proto {
                                        int addr_len);
        int                     (*disconnect)(struct sock *sk, int flags);
 
-       struct sock *           (*accept)(struct sock *sk, int flags, int *err);
+       struct sock *           (*accept)(struct sock *sk, int flags, int *err,
+                                         bool kern);
 
        int                     (*ioctl)(struct sock *sk, int cmd,
                                         unsigned long arg);
@@ -1573,7 +1576,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
 int sock_no_bind(struct socket *, struct sockaddr *, int);
 int sock_no_connect(struct socket *, struct sockaddr *, int, int);
 int sock_no_socketpair(struct socket *, struct socket *);
-int sock_no_accept(struct socket *, struct socket *, int);
+int sock_no_accept(struct socket *, struct socket *, int, bool);
 int sock_no_getname(struct socket *, struct sockaddr *, int *, int);
 unsigned int sock_no_poll(struct file *, struct socket *,
                          struct poll_table_struct *);
index 0f1813c1368795994e012d00c607499879c130aa..99e4423eb2b80b142024bed892ddc4a84ac5e576 100644 (file)
@@ -1863,6 +1863,9 @@ struct ib_port_immutable {
 };
 
 struct ib_device {
+       /* Do not access @dma_device directly from ULP nor from HW drivers. */
+       struct device                *dma_device;
+
        char                          name[IB_DEVICE_NAME_MAX];
 
        struct list_head              event_handler_list;
@@ -3007,7 +3010,7 @@ static inline int ib_req_ncomp_notif(struct ib_cq *cq, int wc_cnt)
  */
 static inline int ib_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
 {
-       return dma_mapping_error(&dev->dev, dma_addr);
+       return dma_mapping_error(dev->dma_device, dma_addr);
 }
 
 /**
@@ -3021,7 +3024,7 @@ static inline u64 ib_dma_map_single(struct ib_device *dev,
                                    void *cpu_addr, size_t size,
                                    enum dma_data_direction direction)
 {
-       return dma_map_single(&dev->dev, cpu_addr, size, direction);
+       return dma_map_single(dev->dma_device, cpu_addr, size, direction);
 }
 
 /**
@@ -3035,7 +3038,7 @@ static inline void ib_dma_unmap_single(struct ib_device *dev,
                                       u64 addr, size_t size,
                                       enum dma_data_direction direction)
 {
-       dma_unmap_single(&dev->dev, addr, size, direction);
+       dma_unmap_single(dev->dma_device, addr, size, direction);
 }
 
 /**
@@ -3052,7 +3055,7 @@ static inline u64 ib_dma_map_page(struct ib_device *dev,
                                  size_t size,
                                         enum dma_data_direction direction)
 {
-       return dma_map_page(&dev->dev, page, offset, size, direction);
+       return dma_map_page(dev->dma_device, page, offset, size, direction);
 }
 
 /**
@@ -3066,7 +3069,7 @@ static inline void ib_dma_unmap_page(struct ib_device *dev,
                                     u64 addr, size_t size,
                                     enum dma_data_direction direction)
 {
-       dma_unmap_page(&dev->dev, addr, size, direction);
+       dma_unmap_page(dev->dma_device, addr, size, direction);
 }
 
 /**
@@ -3080,7 +3083,7 @@ static inline int ib_dma_map_sg(struct ib_device *dev,
                                struct scatterlist *sg, int nents,
                                enum dma_data_direction direction)
 {
-       return dma_map_sg(&dev->dev, sg, nents, direction);
+       return dma_map_sg(dev->dma_device, sg, nents, direction);
 }
 
 /**
@@ -3094,7 +3097,7 @@ static inline void ib_dma_unmap_sg(struct ib_device *dev,
                                   struct scatterlist *sg, int nents,
                                   enum dma_data_direction direction)
 {
-       dma_unmap_sg(&dev->dev, sg, nents, direction);
+       dma_unmap_sg(dev->dma_device, sg, nents, direction);
 }
 
 static inline int ib_dma_map_sg_attrs(struct ib_device *dev,
@@ -3102,7 +3105,8 @@ static inline int ib_dma_map_sg_attrs(struct ib_device *dev,
                                      enum dma_data_direction direction,
                                      unsigned long dma_attrs)
 {
-       return dma_map_sg_attrs(&dev->dev, sg, nents, direction, dma_attrs);
+       return dma_map_sg_attrs(dev->dma_device, sg, nents, direction,
+                               dma_attrs);
 }
 
 static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
@@ -3110,7 +3114,7 @@ static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
                                         enum dma_data_direction direction,
                                         unsigned long dma_attrs)
 {
-       dma_unmap_sg_attrs(&dev->dev, sg, nents, direction, dma_attrs);
+       dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction, dma_attrs);
 }
 /**
  * ib_sg_dma_address - Return the DMA address from a scatter/gather entry
@@ -3152,7 +3156,7 @@ static inline void ib_dma_sync_single_for_cpu(struct ib_device *dev,
                                              size_t size,
                                              enum dma_data_direction dir)
 {
-       dma_sync_single_for_cpu(&dev->dev, addr, size, dir);
+       dma_sync_single_for_cpu(dev->dma_device, addr, size, dir);
 }
 
 /**
@@ -3167,7 +3171,7 @@ static inline void ib_dma_sync_single_for_device(struct ib_device *dev,
                                                 size_t size,
                                                 enum dma_data_direction dir)
 {
-       dma_sync_single_for_device(&dev->dev, addr, size, dir);
+       dma_sync_single_for_device(dev->dma_device, addr, size, dir);
 }
 
 /**
@@ -3182,7 +3186,7 @@ static inline void *ib_dma_alloc_coherent(struct ib_device *dev,
                                           dma_addr_t *dma_handle,
                                           gfp_t flag)
 {
-       return dma_alloc_coherent(&dev->dev, size, dma_handle, flag);
+       return dma_alloc_coherent(dev->dma_device, size, dma_handle, flag);
 }
 
 /**
@@ -3196,7 +3200,7 @@ static inline void ib_dma_free_coherent(struct ib_device *dev,
                                        size_t size, void *cpu_addr,
                                        dma_addr_t dma_handle)
 {
-       dma_free_coherent(&dev->dev, size, cpu_addr, dma_handle);
+       dma_free_coherent(dev->dma_device, size, cpu_addr, dma_handle);
 }
 
 /**
index b0e275de6dec0d2be9adf09810e889c89d7ad06c..583875ea136ab228ea14a727581c384f50527211 100644 (file)
@@ -196,6 +196,7 @@ struct iscsi_conn {
        struct iscsi_task       *task;          /* xmit task in progress */
 
        /* xmit */
+       spinlock_t              taskqueuelock;  /* protects the next three lists */
        struct list_head        mgmtqueue;      /* mgmt (control) xmit queue */
        struct list_head        cmdqueue;       /* data-path cmd queue */
        struct list_head        requeue;        /* tasks needing another run */
index 6f22b39f1b0c3bc8bb1812a631a638ef1987a784..080c7ce9bae8892a43838043d986282a1385283a 100644 (file)
@@ -472,6 +472,10 @@ static inline int scsi_device_created(struct scsi_device *sdev)
                sdev->sdev_state == SDEV_CREATED_BLOCK;
 }
 
+int scsi_internal_device_block(struct scsi_device *sdev, bool wait);
+int scsi_internal_device_unblock(struct scsi_device *sdev,
+                                enum scsi_device_state new_state);
+
 /* accessor functions for the SCSI parameters */
 static inline int scsi_device_sync(struct scsi_device *sdev)
 {
index b54b98dc2d4a77681dd3ecf883d75e062589ee8c..1b0f447ce850f015e64dd27e47751fe945cbb2ec 100644 (file)
@@ -4,7 +4,12 @@
 #include <linux/types.h>
 #include <target/target_core_base.h>
 
-#define TRANSPORT_FLAG_PASSTHROUGH             1
+#define TRANSPORT_FLAG_PASSTHROUGH             0x1
+/*
+ * ALUA commands, state checks and setup operations are handled by the
+ * backend module.
+ */
+#define TRANSPORT_FLAG_PASSTHROUGH_ALUA                0x2
 
 struct request_queue;
 struct scatterlist;
index 37c274e61acceee74d792a240b8f3695f0d78085..4b784b6e21c0d9cb533b31997883d7dd447343bf 100644 (file)
@@ -299,7 +299,7 @@ struct t10_alua_tg_pt_gp {
        struct list_head tg_pt_gp_lun_list;
        struct se_lun *tg_pt_gp_alua_lun;
        struct se_node_acl *tg_pt_gp_alua_nacl;
-       struct delayed_work tg_pt_gp_transition_work;
+       struct work_struct tg_pt_gp_transition_work;
        struct completion *tg_pt_gp_transition_complete;
 };
 
index 9b1462e38b821a762b284b44a20a96de9f0930d9..a076cf1a3a23be2fbee73dab483e051b37b2370c 100644 (file)
@@ -730,9 +730,11 @@ __SYSCALL(__NR_pkey_mprotect, sys_pkey_mprotect)
 __SYSCALL(__NR_pkey_alloc,    sys_pkey_alloc)
 #define __NR_pkey_free 290
 __SYSCALL(__NR_pkey_free,     sys_pkey_free)
+#define __NR_statx 291
+__SYSCALL(__NR_statx,     sys_statx)
 
 #undef __NR_syscalls
-#define __NR_syscalls 291
+#define __NR_syscalls 292
 
 /*
  * All syscalls below here should go away really,
index 407cb55df6ac178e11620fd9554cc913e30b401c..7fb97863c94577d7b9f583abe8a41fe14f54b734 100644 (file)
@@ -33,8 +33,8 @@ extern "C" {
 #define OMAP_PARAM_CHIPSET_ID  1       /* ie. 0x3430, 0x4430, etc */
 
 struct drm_omap_param {
-       uint64_t param;                 /* in */
-       uint64_t value;                 /* in (set_param), out (get_param) */
+       __u64 param;                    /* in */
+       __u64 value;                    /* in (set_param), out (get_param) */
 };
 
 #define OMAP_BO_SCANOUT                0x00000001      /* scanout capable (phys contiguous) */
@@ -53,18 +53,18 @@ struct drm_omap_param {
 #define OMAP_BO_TILED          (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
 
 union omap_gem_size {
-       uint32_t bytes;         /* (for non-tiled formats) */
+       __u32 bytes;            /* (for non-tiled formats) */
        struct {
-               uint16_t width;
-               uint16_t height;
+               __u16 width;
+               __u16 height;
        } tiled;                /* (for tiled formats) */
 };
 
 struct drm_omap_gem_new {
        union omap_gem_size size;       /* in */
-       uint32_t flags;                 /* in */
-       uint32_t handle;                /* out */
-       uint32_t __pad;
+       __u32 flags;                    /* in */
+       __u32 handle;                   /* out */
+       __u32 __pad;
 };
 
 /* mask of operations: */
@@ -74,33 +74,33 @@ enum omap_gem_op {
 };
 
 struct drm_omap_gem_cpu_prep {
-       uint32_t handle;                /* buffer handle (in) */
-       uint32_t op;                    /* mask of omap_gem_op (in) */
+       __u32 handle;                   /* buffer handle (in) */
+       __u32 op;                       /* mask of omap_gem_op (in) */
 };
 
 struct drm_omap_gem_cpu_fini {
-       uint32_t handle;                /* buffer handle (in) */
-       uint32_t op;                    /* mask of omap_gem_op (in) */
+       __u32 handle;                   /* buffer handle (in) */
+       __u32 op;                       /* mask of omap_gem_op (in) */
        /* TODO maybe here we pass down info about what regions are touched
         * by sw so we can be clever about cache ops?  For now a placeholder,
         * set to zero and we just do full buffer flush..
         */
-       uint32_t nregions;
-       uint32_t __pad;
+       __u32 nregions;
+       __u32 __pad;
 };
 
 struct drm_omap_gem_info {
-       uint32_t handle;                /* buffer handle (in) */
-       uint32_t pad;
-       uint64_t offset;                /* mmap offset (out) */
+       __u32 handle;                   /* buffer handle (in) */
+       __u32 pad;
+       __u64 offset;                   /* mmap offset (out) */
        /* note: in case of tiled buffers, the user virtual size can be
         * different from the physical size (ie. how many pages are needed
         * to back the object) which is returned in DRM_IOCTL_GEM_OPEN..
         * This size here is the one that should be used if you want to
         * mmap() the buffer:
         */
-       uint32_t size;                  /* virtual size for mmap'ing (out) */
-       uint32_t __pad;
+       __u32 size;                     /* virtual size for mmap'ing (out) */
+       __u32 __pad;
 };
 
 #define DRM_OMAP_GET_PARAM             0x00
index db4c253f8011b2f483ddd1ffc09f4f04a93fdc0a..dcfc3a5a9cb1d20f29bbac00c6ef315006e9d208 100644 (file)
@@ -713,33 +713,6 @@ enum btrfs_err_code {
        BTRFS_ERROR_DEV_ONLY_WRITABLE,
        BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS
 };
-/* An error code to error string mapping for the kernel
-*  error codes
-*/
-static inline char *btrfs_err_str(enum btrfs_err_code err_code)
-{
-       switch (err_code) {
-               case BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET:
-                       return "unable to go below two devices on raid1";
-               case BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET:
-                       return "unable to go below four devices on raid10";
-               case BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET:
-                       return "unable to go below two devices on raid5";
-               case BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET:
-                       return "unable to go below three devices on raid6";
-               case BTRFS_ERROR_DEV_TGT_REPLACE:
-                       return "unable to remove the dev_replace target dev";
-               case BTRFS_ERROR_DEV_MISSING_NOT_FOUND:
-                       return "no missing devices found to remove";
-               case BTRFS_ERROR_DEV_ONLY_WRITABLE:
-                       return "unable to remove the only writeable device";
-               case BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS:
-                       return "add/delete/balance/replace/resize operation "\
-                               "in progress";
-               default:
-                       return NULL;
-       }
-}
 
 #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
                                   struct btrfs_ioctl_vol_args)
index d08c63f3dd6ff47c7cf090927e91f27cfc0d767f..0c5d5dd61b6ab1d2039686d25683e6dffa1f634e 100644 (file)
@@ -64,7 +64,7 @@ struct packet_diag_mclist {
        __u32   pdmc_count;
        __u16   pdmc_type;
        __u16   pdmc_alen;
-       __u8    pdmc_addr[MAX_ADDR_LEN];
+       __u8    pdmc_addr[32]; /* MAX_ADDR_LEN */
 };
 
 struct packet_diag_ring {
index da7cd62bace746879e154829b5ecad5f6cd87c00..0b3d30837a9f6456aabe028f5f9931b3593d778c 100644 (file)
@@ -34,6 +34,7 @@
 #define MLX5_ABI_USER_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>    /* For ETH_ALEN. */
 
 enum {
        MLX5_QP_FLAG_SIGNATURE          = 1 << 0,
@@ -66,7 +67,7 @@ struct mlx5_ib_alloc_ucontext_req {
 };
 
 enum mlx5_lib_caps {
-       MLX5_LIB_CAP_4K_UAR     = (u64)1 << 0,
+       MLX5_LIB_CAP_4K_UAR     = (__u64)1 << 0,
 };
 
 struct mlx5_ib_alloc_ucontext_req_v2 {
index ef8e2a8ad0afc85da51bc3fca00a26fa3768ff16..6b083d327e982c0c5deb7895ce6e7c6b1094c8a6 100644 (file)
@@ -46,6 +46,7 @@
 #define DECON_FRAMEFIFO_STATUS         0x0524
 #define DECON_CMU                      0x1404
 #define DECON_UPDATE                   0x1410
+#define DECON_CRFMID                   0x1414
 #define DECON_UPDATE_SCHEME            0x1438
 #define DECON_VIDCON1                  0x2000
 #define DECON_VIDCON2                  0x2004
 
 /* VIDINTCON0 */
 #define VIDINTCON0_FRAMEDONE           (1 << 17)
+#define VIDINTCON0_FRAMESEL_BP         (0 << 15)
+#define VIDINTCON0_FRAMESEL_VS         (1 << 15)
+#define VIDINTCON0_FRAMESEL_AC         (2 << 15)
+#define VIDINTCON0_FRAMESEL_FP         (3 << 15)
 #define VIDINTCON0_INTFRMEN            (1 << 12)
 #define VIDINTCON0_INTEN               (1 << 0)
 
 #define STANDALONE_UPDATE_F            (1 << 0)
 
 /* DECON_VIDCON1 */
+#define VIDCON1_LINECNT_MASK           (0x0fff << 16)
+#define VIDCON1_I80_ACTIVE             (1 << 15)
+#define VIDCON1_VSTATUS_MASK           (0x3 << 13)
+#define VIDCON1_VSTATUS_VS             (0 << 13)
+#define VIDCON1_VSTATUS_BP             (1 << 13)
+#define VIDCON1_VSTATUS_AC             (2 << 13)
+#define VIDCON1_VSTATUS_FP             (3 << 13)
 #define VIDCON1_VCLK_MASK              (0x3 << 9)
 #define VIDCON1_VCLK_RUN_VDEN_DISABLE  (0x3 << 9)
 #define VIDCON1_VCLK_HOLD              (0x0 << 9)
index e794544f5e63334afccadf6cc70f5fb2541e1e2e..2f4964cfde0b4f142778c199e606dc3d519ebbf0 100644 (file)
 #include <linux/kthread.h>
 #include <linux/kernel.h>
 #include <linux/syscalls.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/mutex.h>
+#include <linux/gfp.h>
 
 #include <linux/audit.h>
 
@@ -90,13 +94,34 @@ static u32  audit_default;
 /* If auditing cannot proceed, audit_failure selects what happens. */
 static u32     audit_failure = AUDIT_FAIL_PRINTK;
 
-/*
- * If audit records are to be written to the netlink socket, audit_pid
- * contains the pid of the auditd process and audit_nlk_portid contains
- * the portid to use to send netlink messages to that process.
+/* private audit network namespace index */
+static unsigned int audit_net_id;
+
+/**
+ * struct audit_net - audit private network namespace data
+ * @sk: communication socket
+ */
+struct audit_net {
+       struct sock *sk;
+};
+
+/**
+ * struct auditd_connection - kernel/auditd connection state
+ * @pid: auditd PID
+ * @portid: netlink portid
+ * @net: the associated network namespace
+ * @lock: spinlock to protect write access
+ *
+ * Description:
+ * This struct is RCU protected; you must either hold the RCU lock for reading
+ * or the included spinlock for writing.
  */
-int            audit_pid;
-static __u32   audit_nlk_portid;
+static struct auditd_connection {
+       int pid;
+       u32 portid;
+       struct net *net;
+       spinlock_t lock;
+} auditd_conn;
 
 /* If audit_rate_limit is non-zero, limit the rate of sending audit records
  * to that number per second.  This prevents DoS attacks, but results in
@@ -123,10 +148,6 @@ u32                audit_sig_sid = 0;
 */
 static atomic_t        audit_lost = ATOMIC_INIT(0);
 
-/* The netlink socket. */
-static struct sock *audit_sock;
-static unsigned int audit_net_id;
-
 /* Hash for inode-based rules */
 struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
 
@@ -139,6 +160,7 @@ static LIST_HEAD(audit_freelist);
 
 /* queue msgs to send via kauditd_task */
 static struct sk_buff_head audit_queue;
+static void kauditd_hold_skb(struct sk_buff *skb);
 /* queue msgs due to temporary unicast send problems */
 static struct sk_buff_head audit_retry_queue;
 /* queue msgs waiting for new auditd connection */
@@ -192,6 +214,43 @@ struct audit_reply {
        struct sk_buff *skb;
 };
 
+/**
+ * auditd_test_task - Check to see if a given task is an audit daemon
+ * @task: the task to check
+ *
+ * Description:
+ * Return 1 if the task is a registered audit daemon, 0 otherwise.
+ */
+int auditd_test_task(const struct task_struct *task)
+{
+       int rc;
+
+       rcu_read_lock();
+       rc = (auditd_conn.pid && task->tgid == auditd_conn.pid ? 1 : 0);
+       rcu_read_unlock();
+
+       return rc;
+}
+
+/**
+ * audit_get_sk - Return the audit socket for the given network namespace
+ * @net: the destination network namespace
+ *
+ * Description:
+ * Returns the sock pointer if valid, NULL otherwise.  The caller must ensure
+ * that a reference is held for the network namespace while the sock is in use.
+ */
+static struct sock *audit_get_sk(const struct net *net)
+{
+       struct audit_net *aunet;
+
+       if (!net)
+               return NULL;
+
+       aunet = net_generic(net, audit_net_id);
+       return aunet->sk;
+}
+
 static void audit_set_portid(struct audit_buffer *ab, __u32 portid)
 {
        if (ab) {
@@ -210,9 +269,7 @@ void audit_panic(const char *message)
                        pr_err("%s\n", message);
                break;
        case AUDIT_FAIL_PANIC:
-               /* test audit_pid since printk is always losey, why bother? */
-               if (audit_pid)
-                       panic("audit: %s\n", message);
+               panic("audit: %s\n", message);
                break;
        }
 }
@@ -370,21 +427,87 @@ static int audit_set_failure(u32 state)
        return audit_do_config_change("audit_failure", &audit_failure, state);
 }
 
-/*
- * For one reason or another this nlh isn't getting delivered to the userspace
- * audit daemon, just send it to printk.
+/**
+ * auditd_set - Set/Reset the auditd connection state
+ * @pid: auditd PID
+ * @portid: auditd netlink portid
+ * @net: auditd network namespace pointer
+ *
+ * Description:
+ * This function will obtain and drop network namespace references as
+ * necessary.
+ */
+static void auditd_set(int pid, u32 portid, struct net *net)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&auditd_conn.lock, flags);
+       auditd_conn.pid = pid;
+       auditd_conn.portid = portid;
+       if (auditd_conn.net)
+               put_net(auditd_conn.net);
+       if (net)
+               auditd_conn.net = get_net(net);
+       else
+               auditd_conn.net = NULL;
+       spin_unlock_irqrestore(&auditd_conn.lock, flags);
+}
+
+/**
+ * auditd_reset - Disconnect the auditd connection
+ *
+ * Description:
+ * Break the auditd/kauditd connection and move all the queued records into the
+ * hold queue in case auditd reconnects.
+ */
+static void auditd_reset(void)
+{
+       struct sk_buff *skb;
+
+       /* if it isn't already broken, break the connection */
+       rcu_read_lock();
+       if (auditd_conn.pid)
+               auditd_set(0, 0, NULL);
+       rcu_read_unlock();
+
+       /* flush all of the main and retry queues to the hold queue */
+       while ((skb = skb_dequeue(&audit_retry_queue)))
+               kauditd_hold_skb(skb);
+       while ((skb = skb_dequeue(&audit_queue)))
+               kauditd_hold_skb(skb);
+}
+
+/**
+ * kauditd_print_skb - Print the audit record to the ring buffer
+ * @skb: audit record
+ *
+ * Whatever the reason, this packet may not make it to the auditd connection
+ * so write it via printk so the information isn't completely lost.
  */
 static void kauditd_printk_skb(struct sk_buff *skb)
 {
        struct nlmsghdr *nlh = nlmsg_hdr(skb);
        char *data = nlmsg_data(nlh);
 
-       if (nlh->nlmsg_type != AUDIT_EOE) {
-               if (printk_ratelimit())
-                       pr_notice("type=%d %s\n", nlh->nlmsg_type, data);
-               else
-                       audit_log_lost("printk limit exceeded");
-       }
+       if (nlh->nlmsg_type != AUDIT_EOE && printk_ratelimit())
+               pr_notice("type=%d %s\n", nlh->nlmsg_type, data);
+}
+
+/**
+ * kauditd_rehold_skb - Handle a audit record send failure in the hold queue
+ * @skb: audit record
+ *
+ * Description:
+ * This should only be used by the kauditd_thread when it fails to flush the
+ * hold queue.
+ */
+static void kauditd_rehold_skb(struct sk_buff *skb)
+{
+       /* put the record back in the queue at the same place */
+       skb_queue_head(&audit_hold_queue, skb);
+
+       /* fail the auditd connection */
+       auditd_reset();
 }
 
 /**
@@ -421,6 +544,9 @@ static void kauditd_hold_skb(struct sk_buff *skb)
        /* we have no other options - drop the message */
        audit_log_lost("kauditd hold queue overflow");
        kfree_skb(skb);
+
+       /* fail the auditd connection */
+       auditd_reset();
 }
 
 /**
@@ -441,51 +567,122 @@ static void kauditd_retry_skb(struct sk_buff *skb)
 }
 
 /**
- * auditd_reset - Disconnect the auditd connection
+ * auditd_send_unicast_skb - Send a record via unicast to auditd
+ * @skb: audit record
  *
  * Description:
- * Break the auditd/kauditd connection and move all the records in the retry
- * queue into the hold queue in case auditd reconnects.  The audit_cmd_mutex
- * must be held when calling this function.
+ * Send a skb to the audit daemon, returns positive/zero values on success and
+ * negative values on failure; in all cases the skb will be consumed by this
+ * function.  If the send results in -ECONNREFUSED the connection with auditd
+ * will be reset.  This function may sleep so callers should not hold any locks
+ * where this would cause a problem.
  */
-static void auditd_reset(void)
+static int auditd_send_unicast_skb(struct sk_buff *skb)
 {
-       struct sk_buff *skb;
-
-       /* break the connection */
-       if (audit_sock) {
-               sock_put(audit_sock);
-               audit_sock = NULL;
+       int rc;
+       u32 portid;
+       struct net *net;
+       struct sock *sk;
+
+       /* NOTE: we can't call netlink_unicast while in the RCU section so
+        *       take a reference to the network namespace and grab local
+        *       copies of the namespace, the sock, and the portid; the
+        *       namespace and sock aren't going to go away while we hold a
+        *       reference and if the portid does become invalid after the RCU
+        *       section netlink_unicast() should safely return an error */
+
+       rcu_read_lock();
+       if (!auditd_conn.pid) {
+               rcu_read_unlock();
+               rc = -ECONNREFUSED;
+               goto err;
        }
-       audit_pid = 0;
-       audit_nlk_portid = 0;
+       net = auditd_conn.net;
+       get_net(net);
+       sk = audit_get_sk(net);
+       portid = auditd_conn.portid;
+       rcu_read_unlock();
 
-       /* flush all of the retry queue to the hold queue */
-       while ((skb = skb_dequeue(&audit_retry_queue)))
-               kauditd_hold_skb(skb);
+       rc = netlink_unicast(sk, skb, portid, 0);
+       put_net(net);
+       if (rc < 0)
+               goto err;
+
+       return rc;
+
+err:
+       if (rc == -ECONNREFUSED)
+               auditd_reset();
+       return rc;
 }
 
 /**
- * kauditd_send_unicast_skb - Send a record via unicast to auditd
- * @skb: audit record
+ * kauditd_send_queue - Helper for kauditd_thread to flush skb queues
+ * @sk: the sending sock
+ * @portid: the netlink destination
+ * @queue: the skb queue to process
+ * @retry_limit: limit on number of netlink unicast failures
+ * @skb_hook: per-skb hook for additional processing
+ * @err_hook: hook called if the skb fails the netlink unicast send
+ *
+ * Description:
+ * Run through the given queue and attempt to send the audit records to auditd,
+ * returns zero on success, negative values on failure.  It is up to the caller
+ * to ensure that the @sk is valid for the duration of this function.
+ *
  */
-static int kauditd_send_unicast_skb(struct sk_buff *skb)
+static int kauditd_send_queue(struct sock *sk, u32 portid,
+                             struct sk_buff_head *queue,
+                             unsigned int retry_limit,
+                             void (*skb_hook)(struct sk_buff *skb),
+                             void (*err_hook)(struct sk_buff *skb))
 {
-       int rc;
+       int rc = 0;
+       struct sk_buff *skb;
+       static unsigned int failed = 0;
 
-       /* if we know nothing is connected, don't even try the netlink call */
-       if (!audit_pid)
-               return -ECONNREFUSED;
+       /* NOTE: kauditd_thread takes care of all our locking, we just use
+        *       the netlink info passed to us (e.g. sk and portid) */
+
+       while ((skb = skb_dequeue(queue))) {
+               /* call the skb_hook for each skb we touch */
+               if (skb_hook)
+                       (*skb_hook)(skb);
+
+               /* can we send to anyone via unicast? */
+               if (!sk) {
+                       if (err_hook)
+                               (*err_hook)(skb);
+                       continue;
+               }
 
-       /* get an extra skb reference in case we fail to send */
-       skb_get(skb);
-       rc = netlink_unicast(audit_sock, skb, audit_nlk_portid, 0);
-       if (rc >= 0) {
-               consume_skb(skb);
-               rc = 0;
+               /* grab an extra skb reference in case of error */
+               skb_get(skb);
+               rc = netlink_unicast(sk, skb, portid, 0);
+               if (rc < 0) {
+                       /* fatal failure for our queue flush attempt? */
+                       if (++failed >= retry_limit ||
+                           rc == -ECONNREFUSED || rc == -EPERM) {
+                               /* yes - error processing for the queue */
+                               sk = NULL;
+                               if (err_hook)
+                                       (*err_hook)(skb);
+                               if (!skb_hook)
+                                       goto out;
+                               /* keep processing with the skb_hook */
+                               continue;
+                       } else
+                               /* no - requeue to preserve ordering */
+                               skb_queue_head(queue, skb);
+               } else {
+                       /* it worked - drop the extra reference and continue */
+                       consume_skb(skb);
+                       failed = 0;
+               }
        }
 
-       return rc;
+out:
+       return (rc >= 0 ? 0 : rc);
 }
 
 /*
@@ -493,16 +690,19 @@ static int kauditd_send_unicast_skb(struct sk_buff *skb)
  * @skb: audit record
  *
  * Description:
- * This function doesn't consume an skb as might be expected since it has to
- * copy it anyways.
+ * Write a multicast message to anyone listening in the initial network
+ * namespace.  This function doesn't consume an skb as might be expected since
+ * it has to copy it anyways.
  */
 static void kauditd_send_multicast_skb(struct sk_buff *skb)
 {
        struct sk_buff *copy;
-       struct audit_net *aunet = net_generic(&init_net, audit_net_id);
-       struct sock *sock = aunet->nlsk;
+       struct sock *sock = audit_get_sk(&init_net);
        struct nlmsghdr *nlh;
 
+       /* NOTE: we are not taking an additional reference for init_net since
+        *       we don't have to worry about it going away */
+
        if (!netlink_has_listeners(sock, AUDIT_NLGRP_READLOG))
                return;
 
@@ -526,149 +726,75 @@ static void kauditd_send_multicast_skb(struct sk_buff *skb)
 }
 
 /**
- * kauditd_wake_condition - Return true when it is time to wake kauditd_thread
- *
- * Description:
- * This function is for use by the wait_event_freezable() call in
- * kauditd_thread().
+ * kauditd_thread - Worker thread to send audit records to userspace
+ * @dummy: unused
  */
-static int kauditd_wake_condition(void)
-{
-       static int pid_last = 0;
-       int rc;
-       int pid = audit_pid;
-
-       /* wake on new messages or a change in the connected auditd */
-       rc = skb_queue_len(&audit_queue) || (pid && pid != pid_last);
-       if (rc)
-               pid_last = pid;
-
-       return rc;
-}
-
 static int kauditd_thread(void *dummy)
 {
        int rc;
-       int auditd = 0;
-       int reschedule = 0;
-       struct sk_buff *skb;
-       struct nlmsghdr *nlh;
+       u32 portid = 0;
+       struct net *net = NULL;
+       struct sock *sk = NULL;
 
 #define UNICAST_RETRIES 5
-#define AUDITD_BAD(x,y) \
-       ((x) == -ECONNREFUSED || (x) == -EPERM || ++(y) >= UNICAST_RETRIES)
-
-       /* NOTE: we do invalidate the auditd connection flag on any sending
-        * errors, but we only "restore" the connection flag at specific places
-        * in the loop in order to help ensure proper ordering of audit
-        * records */
 
        set_freezable();
        while (!kthread_should_stop()) {
-               /* NOTE: possible area for future improvement is to look at
-                *       the hold and retry queues, since only this thread
-                *       has access to these queues we might be able to do
-                *       our own queuing and skip some/all of the locking */
-
-               /* NOTE: it might be a fun experiment to split the hold and
-                *       retry queue handling to another thread, but the
-                *       synchronization issues and other overhead might kill
-                *       any performance gains */
+               /* NOTE: see the lock comments in auditd_send_unicast_skb() */
+               rcu_read_lock();
+               if (!auditd_conn.pid) {
+                       rcu_read_unlock();
+                       goto main_queue;
+               }
+               net = auditd_conn.net;
+               get_net(net);
+               sk = audit_get_sk(net);
+               portid = auditd_conn.portid;
+               rcu_read_unlock();
 
                /* attempt to flush the hold queue */
-               while (auditd && (skb = skb_dequeue(&audit_hold_queue))) {
-                       rc = kauditd_send_unicast_skb(skb);
-                       if (rc) {
-                               /* requeue to the same spot */
-                               skb_queue_head(&audit_hold_queue, skb);
-
-                               auditd = 0;
-                               if (AUDITD_BAD(rc, reschedule)) {
-                                       mutex_lock(&audit_cmd_mutex);
-                                       auditd_reset();
-                                       mutex_unlock(&audit_cmd_mutex);
-                                       reschedule = 0;
-                               }
-                       } else
-                               /* we were able to send successfully */
-                               reschedule = 0;
+               rc = kauditd_send_queue(sk, portid,
+                                       &audit_hold_queue, UNICAST_RETRIES,
+                                       NULL, kauditd_rehold_skb);
+               if (rc < 0) {
+                       sk = NULL;
+                       goto main_queue;
                }
 
                /* attempt to flush the retry queue */
-               while (auditd && (skb = skb_dequeue(&audit_retry_queue))) {
-                       rc = kauditd_send_unicast_skb(skb);
-                       if (rc) {
-                               auditd = 0;
-                               if (AUDITD_BAD(rc, reschedule)) {
-                                       kauditd_hold_skb(skb);
-                                       mutex_lock(&audit_cmd_mutex);
-                                       auditd_reset();
-                                       mutex_unlock(&audit_cmd_mutex);
-                                       reschedule = 0;
-                               } else
-                                       /* temporary problem (we hope), queue
-                                        * to the same spot and retry */
-                                       skb_queue_head(&audit_retry_queue, skb);
-                       } else
-                               /* we were able to send successfully */
-                               reschedule = 0;
+               rc = kauditd_send_queue(sk, portid,
+                                       &audit_retry_queue, UNICAST_RETRIES,
+                                       NULL, kauditd_hold_skb);
+               if (rc < 0) {
+                       sk = NULL;
+                       goto main_queue;
                }
 
-               /* standard queue processing, try to be as quick as possible */
-quick_loop:
-               skb = skb_dequeue(&audit_queue);
-               if (skb) {
-                       /* setup the netlink header, see the comments in
-                        * kauditd_send_multicast_skb() for length quirks */
-                       nlh = nlmsg_hdr(skb);
-                       nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
-
-                       /* attempt to send to any multicast listeners */
-                       kauditd_send_multicast_skb(skb);
-
-                       /* attempt to send to auditd, queue on failure */
-                       if (auditd) {
-                               rc = kauditd_send_unicast_skb(skb);
-                               if (rc) {
-                                       auditd = 0;
-                                       if (AUDITD_BAD(rc, reschedule)) {
-                                               mutex_lock(&audit_cmd_mutex);
-                                               auditd_reset();
-                                               mutex_unlock(&audit_cmd_mutex);
-                                               reschedule = 0;
-                                       }
-
-                                       /* move to the retry queue */
-                                       kauditd_retry_skb(skb);
-                               } else
-                                       /* everything is working so go fast! */
-                                       goto quick_loop;
-                       } else if (reschedule)
-                               /* we are currently having problems, move to
-                                * the retry queue */
-                               kauditd_retry_skb(skb);
-                       else
-                               /* dump the message via printk and hold it */
-                               kauditd_hold_skb(skb);
-               } else {
-                       /* we have flushed the backlog so wake everyone */
-                       wake_up(&audit_backlog_wait);
-
-                       /* if everything is okay with auditd (if present), go
-                        * to sleep until there is something new in the queue
-                        * or we have a change in the connected auditd;
-                        * otherwise simply reschedule to give things a chance
-                        * to recover */
-                       if (reschedule) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule();
-                       } else
-                               wait_event_freezable(kauditd_wait,
-                                                    kauditd_wake_condition());
-
-                       /* update the auditd connection status */
-                       auditd = (audit_pid ? 1 : 0);
+main_queue:
+               /* process the main queue - do the multicast send and attempt
+                * unicast, dump failed record sends to the retry queue; if
+                * sk == NULL due to previous failures we will just do the
+                * multicast send and move the record to the retry queue */
+               kauditd_send_queue(sk, portid, &audit_queue, 1,
+                                  kauditd_send_multicast_skb,
+                                  kauditd_retry_skb);
+
+               /* drop our netns reference, no auditd sends past this line */
+               if (net) {
+                       put_net(net);
+                       net = NULL;
                }
+               sk = NULL;
+
+               /* we have processed all the queues so wake everyone */
+               wake_up(&audit_backlog_wait);
+
+               /* NOTE: we want to wake up if there is anything on the queue,
+                *       regardless of if an auditd is connected, as we need to
+                *       do the multicast send and rotate records from the
+                *       main queue to the retry/hold queues */
+               wait_event_freezable(kauditd_wait,
+                                    (skb_queue_len(&audit_queue) ? 1 : 0));
        }
 
        return 0;
@@ -678,17 +804,16 @@ int audit_send_list(void *_dest)
 {
        struct audit_netlink_list *dest = _dest;
        struct sk_buff *skb;
-       struct net *net = dest->net;
-       struct audit_net *aunet = net_generic(net, audit_net_id);
+       struct sock *sk = audit_get_sk(dest->net);
 
        /* wait for parent to finish and send an ACK */
        mutex_lock(&audit_cmd_mutex);
        mutex_unlock(&audit_cmd_mutex);
 
        while ((skb = __skb_dequeue(&dest->q)) != NULL)
-               netlink_unicast(aunet->nlsk, skb, dest->portid, 0);
+               netlink_unicast(sk, skb, dest->portid, 0);
 
-       put_net(net);
+       put_net(dest->net);
        kfree(dest);
 
        return 0;
@@ -722,16 +847,15 @@ out_kfree_skb:
 static int audit_send_reply_thread(void *arg)
 {
        struct audit_reply *reply = (struct audit_reply *)arg;
-       struct net *net = reply->net;
-       struct audit_net *aunet = net_generic(net, audit_net_id);
+       struct sock *sk = audit_get_sk(reply->net);
 
        mutex_lock(&audit_cmd_mutex);
        mutex_unlock(&audit_cmd_mutex);
 
        /* Ignore failure. It'll only happen if the sender goes away,
           because our timeout is set to infinite. */
-       netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0);
-       put_net(net);
+       netlink_unicast(sk, reply->skb, reply->portid, 0);
+       put_net(reply->net);
        kfree(reply);
        return 0;
 }
@@ -949,12 +1073,12 @@ static int audit_set_feature(struct sk_buff *skb)
 
 static int audit_replace(pid_t pid)
 {
-       struct sk_buff *skb = audit_make_reply(0, 0, AUDIT_REPLACE, 0, 0,
-                                              &pid, sizeof(pid));
+       struct sk_buff *skb;
 
+       skb = audit_make_reply(0, 0, AUDIT_REPLACE, 0, 0, &pid, sizeof(pid));
        if (!skb)
                return -ENOMEM;
-       return netlink_unicast(audit_sock, skb, audit_nlk_portid, 0);
+       return auditd_send_unicast_skb(skb);
 }
 
 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
@@ -981,7 +1105,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                memset(&s, 0, sizeof(s));
                s.enabled               = audit_enabled;
                s.failure               = audit_failure;
-               s.pid                   = audit_pid;
+               rcu_read_lock();
+               s.pid                   = auditd_conn.pid;
+               rcu_read_unlock();
                s.rate_limit            = audit_rate_limit;
                s.backlog_limit         = audit_backlog_limit;
                s.lost                  = atomic_read(&audit_lost);
@@ -1014,30 +1140,44 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                         *       from the initial pid namespace, but something
                         *       to keep in mind if this changes */
                        int new_pid = s.pid;
+                       pid_t auditd_pid;
                        pid_t requesting_pid = task_tgid_vnr(current);
 
-                       if ((!new_pid) && (requesting_pid != audit_pid)) {
-                               audit_log_config_change("audit_pid", new_pid, audit_pid, 0);
+                       /* test the auditd connection */
+                       audit_replace(requesting_pid);
+
+                       rcu_read_lock();
+                       auditd_pid = auditd_conn.pid;
+                       /* only the current auditd can unregister itself */
+                       if ((!new_pid) && (requesting_pid != auditd_pid)) {
+                               rcu_read_unlock();
+                               audit_log_config_change("audit_pid", new_pid,
+                                                       auditd_pid, 0);
                                return -EACCES;
                        }
-                       if (audit_pid && new_pid &&
-                           audit_replace(requesting_pid) != -ECONNREFUSED) {
-                               audit_log_config_change("audit_pid", new_pid, audit_pid, 0);
+                       /* replacing a healthy auditd is not allowed */
+                       if (auditd_pid && new_pid) {
+                               rcu_read_unlock();
+                               audit_log_config_change("audit_pid", new_pid,
+                                                       auditd_pid, 0);
                                return -EEXIST;
                        }
+                       rcu_read_unlock();
+
                        if (audit_enabled != AUDIT_OFF)
-                               audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
+                               audit_log_config_change("audit_pid", new_pid,
+                                                       auditd_pid, 1);
+
                        if (new_pid) {
-                               if (audit_sock)
-                                       sock_put(audit_sock);
-                               audit_pid = new_pid;
-                               audit_nlk_portid = NETLINK_CB(skb).portid;
-                               sock_hold(skb->sk);
-                               audit_sock = skb->sk;
-                       } else {
+                               /* register a new auditd connection */
+                               auditd_set(new_pid,
+                                          NETLINK_CB(skb).portid,
+                                          sock_net(NETLINK_CB(skb).sk));
+                               /* try to process any backlog */
+                               wake_up_interruptible(&kauditd_wait);
+                       } else
+                               /* unregister the auditd connection */
                                auditd_reset();
-                       }
-                       wake_up_interruptible(&kauditd_wait);
                }
                if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
                        err = audit_set_rate_limit(s.rate_limit);
@@ -1090,7 +1230,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                if (err)
                                        break;
                        }
-                       mutex_unlock(&audit_cmd_mutex);
                        audit_log_common_recv_msg(&ab, msg_type);
                        if (msg_type != AUDIT_USER_TTY)
                                audit_log_format(ab, " msg='%.*s'",
@@ -1108,7 +1247,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        }
                        audit_set_portid(ab, NETLINK_CB(skb).portid);
                        audit_log_end(ab);
-                       mutex_lock(&audit_cmd_mutex);
                }
                break;
        case AUDIT_ADD_RULE:
@@ -1298,26 +1436,26 @@ static int __net_init audit_net_init(struct net *net)
 
        struct audit_net *aunet = net_generic(net, audit_net_id);
 
-       aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
-       if (aunet->nlsk == NULL) {
+       aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
+       if (aunet->sk == NULL) {
                audit_panic("cannot initialize netlink socket in namespace");
                return -ENOMEM;
        }
-       aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+       aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+
        return 0;
 }
 
 static void __net_exit audit_net_exit(struct net *net)
 {
        struct audit_net *aunet = net_generic(net, audit_net_id);
-       struct sock *sock = aunet->nlsk;
-       mutex_lock(&audit_cmd_mutex);
-       if (sock == audit_sock)
+
+       rcu_read_lock();
+       if (net == auditd_conn.net)
                auditd_reset();
-       mutex_unlock(&audit_cmd_mutex);
+       rcu_read_unlock();
 
-       netlink_kernel_release(sock);
-       aunet->nlsk = NULL;
+       netlink_kernel_release(aunet->sk);
 }
 
 static struct pernet_operations audit_net_ops __net_initdata = {
@@ -1335,20 +1473,24 @@ static int __init audit_init(void)
        if (audit_initialized == AUDIT_DISABLED)
                return 0;
 
-       pr_info("initializing netlink subsys (%s)\n",
-               audit_default ? "enabled" : "disabled");
-       register_pernet_subsys(&audit_net_ops);
+       memset(&auditd_conn, 0, sizeof(auditd_conn));
+       spin_lock_init(&auditd_conn.lock);
 
        skb_queue_head_init(&audit_queue);
        skb_queue_head_init(&audit_retry_queue);
        skb_queue_head_init(&audit_hold_queue);
-       audit_initialized = AUDIT_INITIALIZED;
-       audit_enabled = audit_default;
-       audit_ever_enabled |= !!audit_default;
 
        for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
                INIT_LIST_HEAD(&audit_inode_hash[i]);
 
+       pr_info("initializing netlink subsys (%s)\n",
+               audit_default ? "enabled" : "disabled");
+       register_pernet_subsys(&audit_net_ops);
+
+       audit_initialized = AUDIT_INITIALIZED;
+       audit_enabled = audit_default;
+       audit_ever_enabled |= !!audit_default;
+
        kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
        if (IS_ERR(kauditd_task)) {
                int err = PTR_ERR(kauditd_task);
@@ -1519,20 +1661,16 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
        if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE)))
                return NULL;
 
-       /* don't ever fail/sleep on these two conditions:
+       /* NOTE: don't ever fail/sleep on these two conditions:
         * 1. auditd generated record - since we need auditd to drain the
         *    queue; also, when we are checking for auditd, compare PIDs using
         *    task_tgid_vnr() since auditd_pid is set in audit_receive_msg()
         *    using a PID anchored in the caller's namespace
-        * 2. audit command message - record types 1000 through 1099 inclusive
-        *    are command messages/records used to manage the kernel subsystem
-        *    and the audit userspace, blocking on these messages could cause
-        *    problems under load so don't do it (note: not all of these
-        *    command types are valid as record types, but it is quicker to
-        *    just check two ints than a series of ints in a if/switch stmt) */
-       if (!((audit_pid && audit_pid == task_tgid_vnr(current)) ||
-             (type >= 1000 && type <= 1099))) {
-               long sleep_time = audit_backlog_wait_time;
+        * 2. generator holding the audit_cmd_mutex - we don't want to block
+        *    while holding the mutex */
+       if (!(auditd_test_task(current) ||
+             (current == __mutex_owner(&audit_cmd_mutex)))) {
+               long stime = audit_backlog_wait_time;
 
                while (audit_backlog_limit &&
                       (skb_queue_len(&audit_queue) > audit_backlog_limit)) {
@@ -1541,14 +1679,13 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
 
                        /* sleep if we are allowed and we haven't exhausted our
                         * backlog wait limit */
-                       if ((gfp_mask & __GFP_DIRECT_RECLAIM) &&
-                           (sleep_time > 0)) {
+                       if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) {
                                DECLARE_WAITQUEUE(wait, current);
 
                                add_wait_queue_exclusive(&audit_backlog_wait,
                                                         &wait);
                                set_current_state(TASK_UNINTERRUPTIBLE);
-                               sleep_time = schedule_timeout(sleep_time);
+                               stime = schedule_timeout(stime);
                                remove_wait_queue(&audit_backlog_wait, &wait);
                        } else {
                                if (audit_rate_check() && printk_ratelimit())
@@ -2127,15 +2264,27 @@ out:
  */
 void audit_log_end(struct audit_buffer *ab)
 {
+       struct sk_buff *skb;
+       struct nlmsghdr *nlh;
+
        if (!ab)
                return;
-       if (!audit_rate_check()) {
-               audit_log_lost("rate limit exceeded");
-       } else {
-               skb_queue_tail(&audit_queue, ab->skb);
-               wake_up_interruptible(&kauditd_wait);
+
+       if (audit_rate_check()) {
+               skb = ab->skb;
                ab->skb = NULL;
-       }
+
+               /* setup the netlink header, see the comments in
+                * kauditd_send_multicast_skb() for length quirks */
+               nlh = nlmsg_hdr(skb);
+               nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
+
+               /* queue the netlink packet and poke the kauditd thread */
+               skb_queue_tail(&audit_queue, skb);
+               wake_up_interruptible(&kauditd_wait);
+       } else
+               audit_log_lost("rate limit exceeded");
+
        audit_buffer_free(ab);
 }
 
index ca579880303ab475b2c81839a4948bdb128e92f8..0f1cf6d1878ab34a65d72644175ed50055df9a09 100644 (file)
@@ -218,7 +218,7 @@ extern void audit_log_name(struct audit_context *context,
                           struct audit_names *n, const struct path *path,
                           int record_num, int *call_panic);
 
-extern int audit_pid;
+extern int auditd_test_task(const struct task_struct *task);
 
 #define AUDIT_INODE_BUCKETS    32
 extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
@@ -250,10 +250,6 @@ struct audit_netlink_list {
 
 int audit_send_list(void *);
 
-struct audit_net {
-       struct sock *nlsk;
-};
-
 extern int selinux_audit_rule_update(void);
 
 extern struct mutex audit_filter_mutex;
@@ -340,8 +336,7 @@ extern int audit_filter(int msgtype, unsigned int listtype);
 extern int __audit_signal_info(int sig, struct task_struct *t);
 static inline int audit_signal_info(int sig, struct task_struct *t)
 {
-       if (unlikely((audit_pid && t->tgid == audit_pid) ||
-                    (audit_signals && !audit_dummy_context())))
+       if (auditd_test_task(t) || (audit_signals && !audit_dummy_context()))
                return __audit_signal_info(sig, t);
        return 0;
 }
index d6a8de5f8fa3d0ba33c14b20e6341e32d62dab2a..e59ffc7fc522ad9d057c34339807dfe35845d45e 100644 (file)
@@ -762,7 +762,7 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
        struct audit_entry *e;
        enum audit_state state;
 
-       if (audit_pid && tsk->tgid == audit_pid)
+       if (auditd_test_task(tsk))
                return AUDIT_DISABLED;
 
        rcu_read_lock();
@@ -816,7 +816,7 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
 {
        struct audit_names *n;
 
-       if (audit_pid && tsk->tgid == audit_pid)
+       if (auditd_test_task(tsk))
                return;
 
        rcu_read_lock();
@@ -2256,7 +2256,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
        struct audit_context *ctx = tsk->audit_context;
        kuid_t uid = current_uid(), t_uid = task_uid(t);
 
-       if (audit_pid && t->tgid == audit_pid) {
+       if (auditd_test_task(t)) {
                if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
                        audit_sig_pid = task_tgid_nr(tsk);
                        if (uid_valid(tsk->loginuid))
index 3ea87fb19a9416771985d9236f148ffb927ad19b..361a69dfe5434d6afb554477b899e91db90fb29f 100644 (file)
 #include <linux/bpf.h>
 #include <linux/jhash.h>
 #include <linux/filter.h>
+#include <linux/rculist_nulls.h>
 #include "percpu_freelist.h"
 #include "bpf_lru_list.h"
 
 struct bucket {
-       struct hlist_head head;
+       struct hlist_nulls_head head;
        raw_spinlock_t lock;
 };
 
@@ -29,28 +30,26 @@ struct bpf_htab {
                struct pcpu_freelist freelist;
                struct bpf_lru lru;
        };
-       void __percpu *extra_elems;
+       struct htab_elem *__percpu *extra_elems;
        atomic_t count; /* number of elements in this hashtable */
        u32 n_buckets;  /* number of hash buckets */
        u32 elem_size;  /* size of each element in bytes */
 };
 
-enum extra_elem_state {
-       HTAB_NOT_AN_EXTRA_ELEM = 0,
-       HTAB_EXTRA_ELEM_FREE,
-       HTAB_EXTRA_ELEM_USED
-};
-
 /* each htab element is struct htab_elem + key + value */
 struct htab_elem {
        union {
-               struct hlist_node hash_node;
-               struct bpf_htab *htab;
-               struct pcpu_freelist_node fnode;
+               struct hlist_nulls_node hash_node;
+               struct {
+                       void *padding;
+                       union {
+                               struct bpf_htab *htab;
+                               struct pcpu_freelist_node fnode;
+                       };
+               };
        };
        union {
                struct rcu_head rcu;
-               enum extra_elem_state state;
                struct bpf_lru_node lru_node;
        };
        u32 hash;
@@ -71,6 +70,11 @@ static bool htab_is_percpu(const struct bpf_htab *htab)
                htab->map.map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
 }
 
+static bool htab_is_prealloc(const struct bpf_htab *htab)
+{
+       return !(htab->map.map_flags & BPF_F_NO_PREALLOC);
+}
+
 static inline void htab_elem_set_ptr(struct htab_elem *l, u32 key_size,
                                     void __percpu *pptr)
 {
@@ -122,17 +126,20 @@ static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
 
 static int prealloc_init(struct bpf_htab *htab)
 {
+       u32 num_entries = htab->map.max_entries;
        int err = -ENOMEM, i;
 
-       htab->elems = bpf_map_area_alloc(htab->elem_size *
-                                        htab->map.max_entries);
+       if (!htab_is_percpu(htab) && !htab_is_lru(htab))
+               num_entries += num_possible_cpus();
+
+       htab->elems = bpf_map_area_alloc(htab->elem_size * num_entries);
        if (!htab->elems)
                return -ENOMEM;
 
        if (!htab_is_percpu(htab))
                goto skip_percpu_elems;
 
-       for (i = 0; i < htab->map.max_entries; i++) {
+       for (i = 0; i < num_entries; i++) {
                u32 size = round_up(htab->map.value_size, 8);
                void __percpu *pptr;
 
@@ -160,10 +167,11 @@ skip_percpu_elems:
        if (htab_is_lru(htab))
                bpf_lru_populate(&htab->lru, htab->elems,
                                 offsetof(struct htab_elem, lru_node),
-                                htab->elem_size, htab->map.max_entries);
+                                htab->elem_size, num_entries);
        else
-               pcpu_freelist_populate(&htab->freelist, htab->elems,
-                                      htab->elem_size, htab->map.max_entries);
+               pcpu_freelist_populate(&htab->freelist,
+                                      htab->elems + offsetof(struct htab_elem, fnode),
+                                      htab->elem_size, num_entries);
 
        return 0;
 
@@ -184,16 +192,22 @@ static void prealloc_destroy(struct bpf_htab *htab)
 
 static int alloc_extra_elems(struct bpf_htab *htab)
 {
-       void __percpu *pptr;
+       struct htab_elem *__percpu *pptr, *l_new;
+       struct pcpu_freelist_node *l;
        int cpu;
 
-       pptr = __alloc_percpu_gfp(htab->elem_size, 8, GFP_USER | __GFP_NOWARN);
+       pptr = __alloc_percpu_gfp(sizeof(struct htab_elem *), 8,
+                                 GFP_USER | __GFP_NOWARN);
        if (!pptr)
                return -ENOMEM;
 
        for_each_possible_cpu(cpu) {
-               ((struct htab_elem *)per_cpu_ptr(pptr, cpu))->state =
-                       HTAB_EXTRA_ELEM_FREE;
+               l = pcpu_freelist_pop(&htab->freelist);
+               /* pop will succeed, since prealloc_init()
+                * preallocated extra num_possible_cpus elements
+                */
+               l_new = container_of(l, struct htab_elem, fnode);
+               *per_cpu_ptr(pptr, cpu) = l_new;
        }
        htab->extra_elems = pptr;
        return 0;
@@ -217,6 +231,11 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
        int err, i;
        u64 cost;
 
+       BUILD_BUG_ON(offsetof(struct htab_elem, htab) !=
+                    offsetof(struct htab_elem, hash_node.pprev));
+       BUILD_BUG_ON(offsetof(struct htab_elem, fnode.next) !=
+                    offsetof(struct htab_elem, hash_node.pprev));
+
        if (lru && !capable(CAP_SYS_ADMIN))
                /* LRU implementation is much complicated than other
                 * maps.  Hence, limit to CAP_SYS_ADMIN for now.
@@ -326,29 +345,29 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
                goto free_htab;
 
        for (i = 0; i < htab->n_buckets; i++) {
-               INIT_HLIST_HEAD(&htab->buckets[i].head);
+               INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i);
                raw_spin_lock_init(&htab->buckets[i].lock);
        }
 
-       if (!percpu && !lru) {
-               /* lru itself can remove the least used element, so
-                * there is no need for an extra elem during map_update.
-                */
-               err = alloc_extra_elems(htab);
-               if (err)
-                       goto free_buckets;
-       }
-
        if (prealloc) {
                err = prealloc_init(htab);
                if (err)
-                       goto free_extra_elems;
+                       goto free_buckets;
+
+               if (!percpu && !lru) {
+                       /* lru itself can remove the least used element, so
+                        * there is no need for an extra elem during map_update.
+                        */
+                       err = alloc_extra_elems(htab);
+                       if (err)
+                               goto free_prealloc;
+               }
        }
 
        return &htab->map;
 
-free_extra_elems:
-       free_percpu(htab->extra_elems);
+free_prealloc:
+       prealloc_destroy(htab);
 free_buckets:
        bpf_map_area_free(htab->buckets);
 free_htab:
@@ -366,20 +385,44 @@ static inline struct bucket *__select_bucket(struct bpf_htab *htab, u32 hash)
        return &htab->buckets[hash & (htab->n_buckets - 1)];
 }
 
-static inline struct hlist_head *select_bucket(struct bpf_htab *htab, u32 hash)
+static inline struct hlist_nulls_head *select_bucket(struct bpf_htab *htab, u32 hash)
 {
        return &__select_bucket(htab, hash)->head;
 }
 
-static struct htab_elem *lookup_elem_raw(struct hlist_head *head, u32 hash,
+/* this lookup function can only be called with bucket lock taken */
+static struct htab_elem *lookup_elem_raw(struct hlist_nulls_head *head, u32 hash,
                                         void *key, u32 key_size)
 {
+       struct hlist_nulls_node *n;
+       struct htab_elem *l;
+
+       hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
+               if (l->hash == hash && !memcmp(&l->key, key, key_size))
+                       return l;
+
+       return NULL;
+}
+
+/* can be called without bucket lock. it will repeat the loop in
+ * the unlikely event when elements moved from one bucket into another
+ * while link list is being walked
+ */
+static struct htab_elem *lookup_nulls_elem_raw(struct hlist_nulls_head *head,
+                                              u32 hash, void *key,
+                                              u32 key_size, u32 n_buckets)
+{
+       struct hlist_nulls_node *n;
        struct htab_elem *l;
 
-       hlist_for_each_entry_rcu(l, head, hash_node)
+again:
+       hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
                if (l->hash == hash && !memcmp(&l->key, key, key_size))
                        return l;
 
+       if (unlikely(get_nulls_value(n) != (hash & (n_buckets - 1))))
+               goto again;
+
        return NULL;
 }
 
@@ -387,7 +430,7 @@ static struct htab_elem *lookup_elem_raw(struct hlist_head *head, u32 hash,
 static void *__htab_map_lookup_elem(struct bpf_map *map, void *key)
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        struct htab_elem *l;
        u32 hash, key_size;
 
@@ -400,7 +443,7 @@ static void *__htab_map_lookup_elem(struct bpf_map *map, void *key)
 
        head = select_bucket(htab, hash);
 
-       l = lookup_elem_raw(head, hash, key, key_size);
+       l = lookup_nulls_elem_raw(head, hash, key, key_size, htab->n_buckets);
 
        return l;
 }
@@ -433,8 +476,9 @@ static void *htab_lru_map_lookup_elem(struct bpf_map *map, void *key)
 static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 {
        struct bpf_htab *htab = (struct bpf_htab *)arg;
-       struct htab_elem *l, *tgt_l;
-       struct hlist_head *head;
+       struct htab_elem *l = NULL, *tgt_l;
+       struct hlist_nulls_head *head;
+       struct hlist_nulls_node *n;
        unsigned long flags;
        struct bucket *b;
 
@@ -444,9 +488,9 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 
        raw_spin_lock_irqsave(&b->lock, flags);
 
-       hlist_for_each_entry_rcu(l, head, hash_node)
+       hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
                if (l == tgt_l) {
-                       hlist_del_rcu(&l->hash_node);
+                       hlist_nulls_del_rcu(&l->hash_node);
                        break;
                }
 
@@ -459,7 +503,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
 static int htab_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        struct htab_elem *l, *next_l;
        u32 hash, key_size;
        int i;
@@ -473,7 +517,7 @@ static int htab_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
        head = select_bucket(htab, hash);
 
        /* lookup the key */
-       l = lookup_elem_raw(head, hash, key, key_size);
+       l = lookup_nulls_elem_raw(head, hash, key, key_size, htab->n_buckets);
 
        if (!l) {
                i = 0;
@@ -481,7 +525,7 @@ static int htab_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
        }
 
        /* key was found, get next key in the same bucket */
-       next_l = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(&l->hash_node)),
+       next_l = hlist_nulls_entry_safe(rcu_dereference_raw(hlist_nulls_next_rcu(&l->hash_node)),
                                  struct htab_elem, hash_node);
 
        if (next_l) {
@@ -500,7 +544,7 @@ find_first_elem:
                head = select_bucket(htab, i);
 
                /* pick first element in the bucket */
-               next_l = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),
+               next_l = hlist_nulls_entry_safe(rcu_dereference_raw(hlist_nulls_first_rcu(head)),
                                          struct htab_elem, hash_node);
                if (next_l) {
                        /* if it's not empty, just return it */
@@ -538,12 +582,7 @@ static void htab_elem_free_rcu(struct rcu_head *head)
 
 static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
 {
-       if (l->state == HTAB_EXTRA_ELEM_USED) {
-               l->state = HTAB_EXTRA_ELEM_FREE;
-               return;
-       }
-
-       if (!(htab->map.map_flags & BPF_F_NO_PREALLOC)) {
+       if (htab_is_prealloc(htab)) {
                pcpu_freelist_push(&htab->freelist, &l->fnode);
        } else {
                atomic_dec(&htab->count);
@@ -573,43 +612,43 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
 static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
                                         void *value, u32 key_size, u32 hash,
                                         bool percpu, bool onallcpus,
-                                        bool old_elem_exists)
+                                        struct htab_elem *old_elem)
 {
        u32 size = htab->map.value_size;
-       bool prealloc = !(htab->map.map_flags & BPF_F_NO_PREALLOC);
-       struct htab_elem *l_new;
+       bool prealloc = htab_is_prealloc(htab);
+       struct htab_elem *l_new, **pl_new;
        void __percpu *pptr;
-       int err = 0;
 
        if (prealloc) {
-               l_new = (struct htab_elem *)pcpu_freelist_pop(&htab->freelist);
-               if (!l_new)
-                       err = -E2BIG;
-       } else {
-               if (atomic_inc_return(&htab->count) > htab->map.max_entries) {
-                       atomic_dec(&htab->count);
-                       err = -E2BIG;
+               if (old_elem) {
+                       /* if we're updating the existing element,
+                        * use per-cpu extra elems to avoid freelist_pop/push
+                        */
+                       pl_new = this_cpu_ptr(htab->extra_elems);
+                       l_new = *pl_new;
+                       *pl_new = old_elem;
                } else {
-                       l_new = kmalloc(htab->elem_size,
-                                       GFP_ATOMIC | __GFP_NOWARN);
-                       if (!l_new)
-                               return ERR_PTR(-ENOMEM);
-               }
-       }
+                       struct pcpu_freelist_node *l;
 
-       if (err) {
-               if (!old_elem_exists)
-                       return ERR_PTR(err);
-
-               /* if we're updating the existing element and the hash table
-                * is full, use per-cpu extra elems
-                */
-               l_new = this_cpu_ptr(htab->extra_elems);
-               if (l_new->state != HTAB_EXTRA_ELEM_FREE)
-                       return ERR_PTR(-E2BIG);
-               l_new->state = HTAB_EXTRA_ELEM_USED;
+                       l = pcpu_freelist_pop(&htab->freelist);
+                       if (!l)
+                               return ERR_PTR(-E2BIG);
+                       l_new = container_of(l, struct htab_elem, fnode);
+               }
        } else {
-               l_new->state = HTAB_NOT_AN_EXTRA_ELEM;
+               if (atomic_inc_return(&htab->count) > htab->map.max_entries)
+                       if (!old_elem) {
+                               /* when map is full and update() is replacing
+                                * old element, it's ok to allocate, since
+                                * old element will be freed immediately.
+                                * Otherwise return an error
+                                */
+                               atomic_dec(&htab->count);
+                               return ERR_PTR(-E2BIG);
+                       }
+               l_new = kmalloc(htab->elem_size, GFP_ATOMIC | __GFP_NOWARN);
+               if (!l_new)
+                       return ERR_PTR(-ENOMEM);
        }
 
        memcpy(l_new->key, key, key_size);
@@ -661,7 +700,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value,
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
        struct htab_elem *l_new = NULL, *l_old;
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        unsigned long flags;
        struct bucket *b;
        u32 key_size, hash;
@@ -690,7 +729,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value,
                goto err;
 
        l_new = alloc_htab_elem(htab, key, value, key_size, hash, false, false,
-                               !!l_old);
+                               l_old);
        if (IS_ERR(l_new)) {
                /* all pre-allocated elements are in use or memory exhausted */
                ret = PTR_ERR(l_new);
@@ -700,10 +739,11 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value,
        /* add new element to the head of the list, so that
         * concurrent search will find it before old elem
         */
-       hlist_add_head_rcu(&l_new->hash_node, head);
+       hlist_nulls_add_head_rcu(&l_new->hash_node, head);
        if (l_old) {
-               hlist_del_rcu(&l_old->hash_node);
-               free_htab_elem(htab, l_old);
+               hlist_nulls_del_rcu(&l_old->hash_node);
+               if (!htab_is_prealloc(htab))
+                       free_htab_elem(htab, l_old);
        }
        ret = 0;
 err:
@@ -716,7 +756,7 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
        struct htab_elem *l_new, *l_old = NULL;
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        unsigned long flags;
        struct bucket *b;
        u32 key_size, hash;
@@ -757,10 +797,10 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
        /* add new element to the head of the list, so that
         * concurrent search will find it before old elem
         */
-       hlist_add_head_rcu(&l_new->hash_node, head);
+       hlist_nulls_add_head_rcu(&l_new->hash_node, head);
        if (l_old) {
                bpf_lru_node_set_ref(&l_new->lru_node);
-               hlist_del_rcu(&l_old->hash_node);
+               hlist_nulls_del_rcu(&l_old->hash_node);
        }
        ret = 0;
 
@@ -781,7 +821,7 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
        struct htab_elem *l_new = NULL, *l_old;
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        unsigned long flags;
        struct bucket *b;
        u32 key_size, hash;
@@ -815,12 +855,12 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
                                value, onallcpus);
        } else {
                l_new = alloc_htab_elem(htab, key, value, key_size,
-                                       hash, true, onallcpus, false);
+                                       hash, true, onallcpus, NULL);
                if (IS_ERR(l_new)) {
                        ret = PTR_ERR(l_new);
                        goto err;
                }
-               hlist_add_head_rcu(&l_new->hash_node, head);
+               hlist_nulls_add_head_rcu(&l_new->hash_node, head);
        }
        ret = 0;
 err:
@@ -834,7 +874,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
        struct htab_elem *l_new = NULL, *l_old;
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        unsigned long flags;
        struct bucket *b;
        u32 key_size, hash;
@@ -882,7 +922,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
        } else {
                pcpu_copy_value(htab, htab_elem_get_ptr(l_new, key_size),
                                value, onallcpus);
-               hlist_add_head_rcu(&l_new->hash_node, head);
+               hlist_nulls_add_head_rcu(&l_new->hash_node, head);
                l_new = NULL;
        }
        ret = 0;
@@ -910,7 +950,7 @@ static int htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 static int htab_map_delete_elem(struct bpf_map *map, void *key)
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        struct bucket *b;
        struct htab_elem *l;
        unsigned long flags;
@@ -930,7 +970,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key)
        l = lookup_elem_raw(head, hash, key, key_size);
 
        if (l) {
-               hlist_del_rcu(&l->hash_node);
+               hlist_nulls_del_rcu(&l->hash_node);
                free_htab_elem(htab, l);
                ret = 0;
        }
@@ -942,7 +982,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key)
 static int htab_lru_map_delete_elem(struct bpf_map *map, void *key)
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
-       struct hlist_head *head;
+       struct hlist_nulls_head *head;
        struct bucket *b;
        struct htab_elem *l;
        unsigned long flags;
@@ -962,7 +1002,7 @@ static int htab_lru_map_delete_elem(struct bpf_map *map, void *key)
        l = lookup_elem_raw(head, hash, key, key_size);
 
        if (l) {
-               hlist_del_rcu(&l->hash_node);
+               hlist_nulls_del_rcu(&l->hash_node);
                ret = 0;
        }
 
@@ -977,14 +1017,13 @@ static void delete_all_elements(struct bpf_htab *htab)
        int i;
 
        for (i = 0; i < htab->n_buckets; i++) {
-               struct hlist_head *head = select_bucket(htab, i);
-               struct hlist_node *n;
+               struct hlist_nulls_head *head = select_bucket(htab, i);
+               struct hlist_nulls_node *n;
                struct htab_elem *l;
 
-               hlist_for_each_entry_safe(l, n, head, hash_node) {
-                       hlist_del_rcu(&l->hash_node);
-                       if (l->state != HTAB_EXTRA_ELEM_USED)
-                               htab_elem_free(htab, l);
+               hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
+                       hlist_nulls_del_rcu(&l->hash_node);
+                       htab_elem_free(htab, l);
                }
        }
 }
@@ -1004,7 +1043,7 @@ static void htab_map_free(struct bpf_map *map)
         * not have executed. Wait for them.
         */
        rcu_barrier();
-       if (htab->map.map_flags & BPF_F_NO_PREALLOC)
+       if (!htab_is_prealloc(htab))
                delete_all_elements(htab);
        else
                prealloc_destroy(htab);
index 8bfe0afaee1082186f805a2a37a556247cbfa608..b37bd9ab7f574242722c1d9b0503b896019488b2 100644 (file)
@@ -500,9 +500,15 @@ unlock:
        raw_spin_unlock(&trie->lock);
 }
 
+static int trie_get_next_key(struct bpf_map *map, void *key, void *next_key)
+{
+       return -ENOTSUPP;
+}
+
 static const struct bpf_map_ops trie_ops = {
        .map_alloc = trie_alloc,
        .map_free = trie_free,
+       .map_get_next_key = trie_get_next_key,
        .map_lookup_elem = trie_lookup_elem,
        .map_update_elem = trie_update_elem,
        .map_delete_elem = trie_delete_elem,
index 56eba9caa632adcc118114d8aa55cbab00895495..1dc22f6b49f5e06c4af22222dfb1b32c885ce16a 100644 (file)
@@ -1329,7 +1329,7 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v)
                struct task_struct *task;
                int count = 0;
 
-               seq_printf(seq, "css_set %p\n", cset);
+               seq_printf(seq, "css_set %pK\n", cset);
 
                list_for_each_entry(task, &cset->tasks, cg_list) {
                        if (count++ > MAX_TASKS_SHOWN_PER_CSS)
index e756dae493008e4bc4bf9f87846f818d7349ede8..2237201d66d5dacf1fe952a15d9acc54b1e90b50 100644 (file)
@@ -229,7 +229,7 @@ static int pids_can_fork(struct task_struct *task)
                /* Only log the first time events_limit is incremented. */
                if (atomic64_inc_return(&pids->events_limit) == 1) {
                        pr_info("cgroup: fork rejected by pids controller in ");
-                       pr_cont_cgroup_path(task_cgroup(current, pids_cgrp_id));
+                       pr_cont_cgroup_path(css->cgroup);
                        pr_cont("\n");
                }
                cgroup_file_notify(&pids->events_file);
index f7c063239fa5c74636922743ddb094052b9044c9..37b223e4fc05b74fc50aa51df0c307d65da026c3 100644 (file)
@@ -1335,26 +1335,21 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
        struct cpuhp_step *sp;
        int ret = 0;
 
-       mutex_lock(&cpuhp_state_mutex);
-
        if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
                ret = cpuhp_reserve_state(state);
                if (ret < 0)
-                       goto out;
+                       return ret;
                state = ret;
        }
        sp = cpuhp_get_step(state);
-       if (name && sp->name) {
-               ret = -EBUSY;
-               goto out;
-       }
+       if (name && sp->name)
+               return -EBUSY;
+
        sp->startup.single = startup;
        sp->teardown.single = teardown;
        sp->name = name;
        sp->multi_instance = multi_instance;
        INIT_HLIST_HEAD(&sp->list);
-out:
-       mutex_unlock(&cpuhp_state_mutex);
        return ret;
 }
 
@@ -1428,6 +1423,7 @@ int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node,
                return -EINVAL;
 
        get_online_cpus();
+       mutex_lock(&cpuhp_state_mutex);
 
        if (!invoke || !sp->startup.multi)
                goto add_node;
@@ -1447,16 +1443,14 @@ int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node,
                if (ret) {
                        if (sp->teardown.multi)
                                cpuhp_rollback_install(cpu, state, node);
-                       goto err;
+                       goto unlock;
                }
        }
 add_node:
        ret = 0;
-       mutex_lock(&cpuhp_state_mutex);
        hlist_add_head(node, &sp->list);
+unlock:
        mutex_unlock(&cpuhp_state_mutex);
-
-err:
        put_online_cpus();
        return ret;
 }
@@ -1491,6 +1485,7 @@ int __cpuhp_setup_state(enum cpuhp_state state,
                return -EINVAL;
 
        get_online_cpus();
+       mutex_lock(&cpuhp_state_mutex);
 
        ret = cpuhp_store_callbacks(state, name, startup, teardown,
                                    multi_instance);
@@ -1524,6 +1519,7 @@ int __cpuhp_setup_state(enum cpuhp_state state,
                }
        }
 out:
+       mutex_unlock(&cpuhp_state_mutex);
        put_online_cpus();
        /*
         * If the requested state is CPUHP_AP_ONLINE_DYN, return the
@@ -1547,6 +1543,8 @@ int __cpuhp_state_remove_instance(enum cpuhp_state state,
                return -EINVAL;
 
        get_online_cpus();
+       mutex_lock(&cpuhp_state_mutex);
+
        if (!invoke || !cpuhp_get_teardown_cb(state))
                goto remove;
        /*
@@ -1563,7 +1561,6 @@ int __cpuhp_state_remove_instance(enum cpuhp_state state,
        }
 
 remove:
-       mutex_lock(&cpuhp_state_mutex);
        hlist_del(node);
        mutex_unlock(&cpuhp_state_mutex);
        put_online_cpus();
@@ -1571,6 +1568,7 @@ remove:
        return 0;
 }
 EXPORT_SYMBOL_GPL(__cpuhp_state_remove_instance);
+
 /**
  * __cpuhp_remove_state - Remove the callbacks for an hotplug machine state
  * @state:     The state to remove
@@ -1589,6 +1587,7 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
 
        get_online_cpus();
 
+       mutex_lock(&cpuhp_state_mutex);
        if (sp->multi_instance) {
                WARN(!hlist_empty(&sp->list),
                     "Error: Removing state %d which has instances left.\n",
@@ -1613,6 +1612,7 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
        }
 remove:
        cpuhp_store_callbacks(state, NULL, NULL, NULL, false);
+       mutex_unlock(&cpuhp_state_mutex);
        put_online_cpus();
 }
 EXPORT_SYMBOL(__cpuhp_remove_state);
index a17ed56c8ce1f918519cfbf96ee3c938734ecb08..ff01cba86f430fd29916ab73c755698bf81feff0 100644 (file)
@@ -4256,7 +4256,7 @@ int perf_event_release_kernel(struct perf_event *event)
 
        raw_spin_lock_irq(&ctx->lock);
        /*
-        * Mark this even as STATE_DEAD, there is no external reference to it
+        * Mark this event as STATE_DEAD, there is no external reference to it
         * anymore.
         *
         * Anybody acquiring event->child_mutex after the below loop _must_
@@ -10417,21 +10417,22 @@ void perf_event_free_task(struct task_struct *task)
                        continue;
 
                mutex_lock(&ctx->mutex);
-again:
-               list_for_each_entry_safe(event, tmp, &ctx->pinned_groups,
-                               group_entry)
-                       perf_free_event(event, ctx);
+               raw_spin_lock_irq(&ctx->lock);
+               /*
+                * Destroy the task <-> ctx relation and mark the context dead.
+                *
+                * This is important because even though the task hasn't been
+                * exposed yet the context has been (through child_list).
+                */
+               RCU_INIT_POINTER(task->perf_event_ctxp[ctxn], NULL);
+               WRITE_ONCE(ctx->task, TASK_TOMBSTONE);
+               put_task_struct(task); /* cannot be last */
+               raw_spin_unlock_irq(&ctx->lock);
 
-               list_for_each_entry_safe(event, tmp, &ctx->flexible_groups,
-                               group_entry)
+               list_for_each_entry_safe(event, tmp, &ctx->event_list, event_entry)
                        perf_free_event(event, ctx);
 
-               if (!list_empty(&ctx->pinned_groups) ||
-                               !list_empty(&ctx->flexible_groups))
-                       goto again;
-
                mutex_unlock(&ctx->mutex);
-
                put_ctx(ctx);
        }
 }
@@ -10469,7 +10470,12 @@ const struct perf_event_attr *perf_event_attrs(struct perf_event *event)
 }
 
 /*
- * inherit a event from parent task to child task:
+ * Inherit a event from parent task to child task.
+ *
+ * Returns:
+ *  - valid pointer on success
+ *  - NULL for orphaned events
+ *  - IS_ERR() on error
  */
 static struct perf_event *
 inherit_event(struct perf_event *parent_event,
@@ -10563,6 +10569,16 @@ inherit_event(struct perf_event *parent_event,
        return child_event;
 }
 
+/*
+ * Inherits an event group.
+ *
+ * This will quietly suppress orphaned events; !inherit_event() is not an error.
+ * This matches with perf_event_release_kernel() removing all child events.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - <0 on error
+ */
 static int inherit_group(struct perf_event *parent_event,
              struct task_struct *parent,
              struct perf_event_context *parent_ctx,
@@ -10577,6 +10593,11 @@ static int inherit_group(struct perf_event *parent_event,
                                 child, NULL, child_ctx);
        if (IS_ERR(leader))
                return PTR_ERR(leader);
+       /*
+        * @leader can be NULL here because of is_orphaned_event(). In this
+        * case inherit_event() will create individual events, similar to what
+        * perf_group_detach() would do anyway.
+        */
        list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
                child_ctr = inherit_event(sub, parent, parent_ctx,
                                            child, leader, child_ctx);
@@ -10586,6 +10607,17 @@ static int inherit_group(struct perf_event *parent_event,
        return 0;
 }
 
+/*
+ * Creates the child task context and tries to inherit the event-group.
+ *
+ * Clears @inherited_all on !attr.inherited or error. Note that we'll leave
+ * inherited_all set when we 'fail' to inherit an orphaned event; this is
+ * consistent with perf_event_release_kernel() removing all child events.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - <0 on error
+ */
 static int
 inherit_task_group(struct perf_event *event, struct task_struct *parent,
                   struct perf_event_context *parent_ctx,
@@ -10608,7 +10640,6 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
                 * First allocate and initialize a context for the
                 * child.
                 */
-
                child_ctx = alloc_perf_context(parent_ctx->pmu, child);
                if (!child_ctx)
                        return -ENOMEM;
@@ -10670,7 +10701,7 @@ static int perf_event_init_context(struct task_struct *child, int ctxn)
                ret = inherit_task_group(event, parent, parent_ctx,
                                         child, ctxn, &inherited_all);
                if (ret)
-                       break;
+                       goto out_unlock;
        }
 
        /*
@@ -10686,7 +10717,7 @@ static int perf_event_init_context(struct task_struct *child, int ctxn)
                ret = inherit_task_group(event, parent, parent_ctx,
                                         child, ctxn, &inherited_all);
                if (ret)
-                       break;
+                       goto out_unlock;
        }
 
        raw_spin_lock_irqsave(&parent_ctx->lock, flags);
@@ -10714,6 +10745,7 @@ static int perf_event_init_context(struct task_struct *child, int ctxn)
        }
 
        raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
+out_unlock:
        mutex_unlock(&parent_ctx->mutex);
 
        perf_unpin_context(parent_ctx);
index 229a744b1781be2e4fccc1b5c290bd246d8b8694..45858ec739411f5741667e560552757697441e6b 100644 (file)
@@ -2815,7 +2815,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
 {
        struct hrtimer_sleeper timeout, *to = NULL;
        struct rt_mutex_waiter rt_waiter;
-       struct rt_mutex *pi_mutex = NULL;
        struct futex_hash_bucket *hb;
        union futex_key key2 = FUTEX_KEY_INIT;
        struct futex_q q = futex_q_init;
@@ -2899,6 +2898,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
                if (q.pi_state && (q.pi_state->owner != current)) {
                        spin_lock(q.lock_ptr);
                        ret = fixup_pi_state_owner(uaddr2, &q, current);
+                       if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current)
+                               rt_mutex_unlock(&q.pi_state->pi_mutex);
                        /*
                         * Drop the reference to the pi state which
                         * the requeue_pi() code acquired for us.
@@ -2907,6 +2908,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
                        spin_unlock(q.lock_ptr);
                }
        } else {
+               struct rt_mutex *pi_mutex;
+
                /*
                 * We have been woken up by futex_unlock_pi(), a timeout, or a
                 * signal.  futex_unlock_pi() will not destroy the lock_ptr nor
@@ -2930,18 +2933,19 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
                if (res)
                        ret = (res < 0) ? res : 0;
 
+               /*
+                * If fixup_pi_state_owner() faulted and was unable to handle
+                * the fault, unlock the rt_mutex and return the fault to
+                * userspace.
+                */
+               if (ret && rt_mutex_owner(pi_mutex) == current)
+                       rt_mutex_unlock(pi_mutex);
+
                /* Unqueue and drop the lock. */
                unqueue_me_pi(&q);
        }
 
-       /*
-        * If fixup_pi_state_owner() faulted and was unable to handle the
-        * fault, unlock the rt_mutex and return the fault to userspace.
-        */
-       if (ret == -EFAULT) {
-               if (pi_mutex && rt_mutex_owner(pi_mutex) == current)
-                       rt_mutex_unlock(pi_mutex);
-       } else if (ret == -EINTR) {
+       if (ret == -EINTR) {
                /*
                 * We've already been requeued, but cannot restart by calling
                 * futex_lock_pi() directly. We could restart this syscall, but
index 7bc24d477805d868b932aab7acc6997120931fc5..c65f7989f850d12508045896a2cb98d5b691c068 100644 (file)
@@ -213,10 +213,9 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
                 */
                if (sem->count == 0)
                        break;
-               if (signal_pending_state(state, current)) {
-                       ret = -EINTR;
-                       goto out;
-               }
+               if (signal_pending_state(state, current))
+                       goto out_nolock;
+
                set_current_state(state);
                raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
                schedule();
@@ -224,12 +223,19 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
        }
        /* got the lock */
        sem->count = -1;
-out:
        list_del(&waiter.list);
 
        raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
 
        return ret;
+
+out_nolock:
+       list_del(&waiter.list);
+       if (!list_empty(&sem->wait_list))
+               __rwsem_do_wake(sem, 1);
+       raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
+
+       return -EINTR;
 }
 
 void __sched __down_write(struct rw_semaphore *sem)
index 06123234f1189c86ee42dffdc2d14873b6b16895..07e85e5229da849d33391f97234c1e1fff2c5ce1 100644 (file)
@@ -247,11 +247,9 @@ static void devm_memremap_pages_release(struct device *dev, void *data)
        align_start = res->start & ~(SECTION_SIZE - 1);
        align_size = ALIGN(resource_size(res), SECTION_SIZE);
 
-       lock_device_hotplug();
        mem_hotplug_begin();
        arch_remove_memory(align_start, align_size);
        mem_hotplug_done();
-       unlock_device_hotplug();
 
        untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
        pgmap_radix_release(res);
@@ -364,11 +362,9 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
        if (error)
                goto err_pfn_remap;
 
-       lock_device_hotplug();
        mem_hotplug_begin();
        error = arch_add_memory(nid, align_start, align_size, true);
        mem_hotplug_done();
-       unlock_device_hotplug();
        if (error)
                goto err_add_memory;
 
index cd7cd489f739817f07349e8526812eaa3e110075..54c577578da6899160cf4a611e87a386a2fd7db2 100644 (file)
@@ -584,20 +584,14 @@ static int sugov_start(struct cpufreq_policy *policy)
        for_each_cpu(cpu, policy->cpus) {
                struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
 
+               memset(sg_cpu, 0, sizeof(*sg_cpu));
                sg_cpu->sg_policy = sg_policy;
-               if (policy_is_shared(policy)) {
-                       sg_cpu->util = 0;
-                       sg_cpu->max = 0;
-                       sg_cpu->flags = SCHED_CPUFREQ_RT;
-                       sg_cpu->last_update = 0;
-                       sg_cpu->iowait_boost = 0;
-                       sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
-                       cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
-                                                    sugov_update_shared);
-               } else {
-                       cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
-                                                    sugov_update_single);
-               }
+               sg_cpu->flags = SCHED_CPUFREQ_RT;
+               sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
+               cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
+                                            policy_is_shared(policy) ?
+                                                       sugov_update_shared :
+                                                       sugov_update_single);
        }
        return 0;
 }
index 99b2c33a9fbcb4411fd7b75d6dbaff36bf07f803..a2ce59015642c3ccc753006837a9485b2d9fbcd3 100644 (file)
@@ -445,13 +445,13 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
  *
  * This function returns true if:
  *
- *   runtime / (deadline - t) > dl_runtime / dl_period ,
+ *   runtime / (deadline - t) > dl_runtime / dl_deadline ,
  *
  * IOW we can't recycle current parameters.
  *
- * Notice that the bandwidth check is done against the period. For
+ * Notice that the bandwidth check is done against the deadline. For
  * task with deadline equal to period this is the same of using
- * dl_deadline instead of dl_period in the equation above.
+ * dl_period instead of dl_deadline in the equation above.
  */
 static bool dl_entity_overflow(struct sched_dl_entity *dl_se,
                               struct sched_dl_entity *pi_se, u64 t)
@@ -476,7 +476,7 @@ static bool dl_entity_overflow(struct sched_dl_entity *dl_se,
         * of anything below microseconds resolution is actually fiction
         * (but still we want to give the user that illusion >;).
         */
-       left = (pi_se->dl_period >> DL_SCALE) * (dl_se->runtime >> DL_SCALE);
+       left = (pi_se->dl_deadline >> DL_SCALE) * (dl_se->runtime >> DL_SCALE);
        right = ((dl_se->deadline - t) >> DL_SCALE) *
                (pi_se->dl_runtime >> DL_SCALE);
 
@@ -505,10 +505,15 @@ static void update_dl_entity(struct sched_dl_entity *dl_se,
        }
 }
 
+static inline u64 dl_next_period(struct sched_dl_entity *dl_se)
+{
+       return dl_se->deadline - dl_se->dl_deadline + dl_se->dl_period;
+}
+
 /*
  * If the entity depleted all its runtime, and if we want it to sleep
  * while waiting for some new execution time to become available, we
- * set the bandwidth enforcement timer to the replenishment instant
+ * set the bandwidth replenishment timer to the replenishment instant
  * and try to activate it.
  *
  * Notice that it is important for the caller to know if the timer
@@ -530,7 +535,7 @@ static int start_dl_timer(struct task_struct *p)
         * that it is actually coming from rq->clock and not from
         * hrtimer's time base reading.
         */
-       act = ns_to_ktime(dl_se->deadline);
+       act = ns_to_ktime(dl_next_period(dl_se));
        now = hrtimer_cb_get_time(timer);
        delta = ktime_to_ns(now) - rq_clock(rq);
        act = ktime_add_ns(act, delta);
@@ -638,6 +643,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
                lockdep_unpin_lock(&rq->lock, rf.cookie);
                rq = dl_task_offline_migration(rq, p);
                rf.cookie = lockdep_pin_lock(&rq->lock);
+               update_rq_clock(rq);
 
                /*
                 * Now that the task has been migrated to the new RQ and we
@@ -689,6 +695,37 @@ void init_dl_task_timer(struct sched_dl_entity *dl_se)
        timer->function = dl_task_timer;
 }
 
+/*
+ * During the activation, CBS checks if it can reuse the current task's
+ * runtime and period. If the deadline of the task is in the past, CBS
+ * cannot use the runtime, and so it replenishes the task. This rule
+ * works fine for implicit deadline tasks (deadline == period), and the
+ * CBS was designed for implicit deadline tasks. However, a task with
+ * constrained deadline (deadine < period) might be awakened after the
+ * deadline, but before the next period. In this case, replenishing the
+ * task would allow it to run for runtime / deadline. As in this case
+ * deadline < period, CBS enables a task to run for more than the
+ * runtime / period. In a very loaded system, this can cause a domino
+ * effect, making other tasks miss their deadlines.
+ *
+ * To avoid this problem, in the activation of a constrained deadline
+ * task after the deadline but before the next period, throttle the
+ * task and set the replenishing timer to the begin of the next period,
+ * unless it is boosted.
+ */
+static inline void dl_check_constrained_dl(struct sched_dl_entity *dl_se)
+{
+       struct task_struct *p = dl_task_of(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq_of_se(dl_se));
+
+       if (dl_time_before(dl_se->deadline, rq_clock(rq)) &&
+           dl_time_before(rq_clock(rq), dl_next_period(dl_se))) {
+               if (unlikely(dl_se->dl_boosted || !start_dl_timer(p)))
+                       return;
+               dl_se->dl_throttled = 1;
+       }
+}
+
 static
 int dl_runtime_exceeded(struct sched_dl_entity *dl_se)
 {
@@ -922,6 +959,11 @@ static void dequeue_dl_entity(struct sched_dl_entity *dl_se)
        __dequeue_dl_entity(dl_se);
 }
 
+static inline bool dl_is_constrained(struct sched_dl_entity *dl_se)
+{
+       return dl_se->dl_deadline < dl_se->dl_period;
+}
+
 static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
 {
        struct task_struct *pi_task = rt_mutex_get_top_task(p);
@@ -947,6 +989,15 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
                return;
        }
 
+       /*
+        * Check if a constrained deadline task was activated
+        * after the deadline but before the next period.
+        * If that is the case, the task will be throttled and
+        * the replenishment timer will be set to the next period.
+        */
+       if (!p->dl.dl_throttled && dl_is_constrained(&p->dl))
+               dl_check_constrained_dl(&p->dl);
+
        /*
         * If p is throttled, we do nothing. In fact, if it exhausted
         * its budget it needs a replenishment and, since it now is on
index 7296b7308ecaebb6cca949e1a9e2d4361750f7c6..f15fb2bdbc0dee60d770da951424f8cf0635f5f6 100644 (file)
@@ -169,7 +169,7 @@ static inline int calc_load_write_idx(void)
         * If the folding window started, make sure we start writing in the
         * next idle-delta.
         */
-       if (!time_before(jiffies, calc_load_update))
+       if (!time_before(jiffies, READ_ONCE(calc_load_update)))
                idx++;
 
        return idx & 1;
@@ -202,8 +202,9 @@ void calc_load_exit_idle(void)
        struct rq *this_rq = this_rq();
 
        /*
-        * If we're still before the sample window, we're done.
+        * If we're still before the pending sample window, we're done.
         */
+       this_rq->calc_load_update = READ_ONCE(calc_load_update);
        if (time_before(jiffies, this_rq->calc_load_update))
                return;
 
@@ -212,7 +213,6 @@ void calc_load_exit_idle(void)
         * accounted through the nohz accounting, so skip the entire deal and
         * sync up for the next window.
         */
-       this_rq->calc_load_update = calc_load_update;
        if (time_before(jiffies, this_rq->calc_load_update + 10))
                this_rq->calc_load_update += LOAD_FREQ;
 }
@@ -308,13 +308,15 @@ calc_load_n(unsigned long load, unsigned long exp,
  */
 static void calc_global_nohz(void)
 {
+       unsigned long sample_window;
        long delta, active, n;
 
-       if (!time_before(jiffies, calc_load_update + 10)) {
+       sample_window = READ_ONCE(calc_load_update);
+       if (!time_before(jiffies, sample_window + 10)) {
                /*
                 * Catch-up, fold however many we are behind still
                 */
-               delta = jiffies - calc_load_update - 10;
+               delta = jiffies - sample_window - 10;
                n = 1 + (delta / LOAD_FREQ);
 
                active = atomic_long_read(&calc_load_tasks);
@@ -324,7 +326,7 @@ static void calc_global_nohz(void)
                avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
                avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
 
-               calc_load_update += n * LOAD_FREQ;
+               WRITE_ONCE(calc_load_update, sample_window + n * LOAD_FREQ);
        }
 
        /*
@@ -352,9 +354,11 @@ static inline void calc_global_nohz(void) { }
  */
 void calc_global_load(unsigned long ticks)
 {
+       unsigned long sample_window;
        long active, delta;
 
-       if (time_before(jiffies, calc_load_update + 10))
+       sample_window = READ_ONCE(calc_load_update);
+       if (time_before(jiffies, sample_window + 10))
                return;
 
        /*
@@ -371,7 +375,7 @@ void calc_global_load(unsigned long ticks)
        avenrun[1] = calc_load(avenrun[1], EXP_5, active);
        avenrun[2] = calc_load(avenrun[2], EXP_15, active);
 
-       calc_load_update += LOAD_FREQ;
+       WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);
 
        /*
         * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk.
index 072cbc9b175dc1efbe95c14858f810f92db12130..c0168b7da1eaf22c216147ca5ebd03ef7311dca8 100644 (file)
@@ -1507,6 +1507,7 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
        struct timer_list *timer = &dwork->timer;
        struct work_struct *work = &dwork->work;
 
+       WARN_ON_ONCE(!wq);
        WARN_ON_ONCE(timer->function != delayed_work_timer_fn ||
                     timer->data != (unsigned long)dwork);
        WARN_ON_ONCE(timer_pending(timer));
index c74bad1bf6e8f2423c19cb8b6c3a386272ef8252..04aa405350dce8656db4293a34e95e9bfbe166d8 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1455,7 +1455,7 @@ static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end,
                        if (!gup_huge_pd(__hugepd(p4d_val(p4d)), addr,
                                         P4D_SHIFT, next, write, pages, nr))
                                return 0;
-               } else if (!gup_p4d_range(p4d, addr, next, write, pages, nr))
+               } else if (!gup_pud_range(p4d, addr, next, write, pages, nr))
                        return 0;
        } while (p4dp++, addr = next, addr != end);
 
index 295479b792ec488b6d984ef98e7e715f6ac162b4..6fa7208bcd564ec8fb6bcf25e206aef9bd724ecb 100644 (file)
@@ -125,9 +125,12 @@ void put_online_mems(void)
 
 }
 
+/* Serializes write accesses to mem_hotplug.active_writer. */
+static DEFINE_MUTEX(memory_add_remove_lock);
+
 void mem_hotplug_begin(void)
 {
-       assert_held_device_hotplug();
+       mutex_lock(&memory_add_remove_lock);
 
        mem_hotplug.active_writer = current;
 
@@ -147,6 +150,7 @@ void mem_hotplug_done(void)
        mem_hotplug.active_writer = NULL;
        mutex_unlock(&mem_hotplug.lock);
        memhp_lock_release();
+       mutex_unlock(&memory_add_remove_lock);
 }
 
 /* add this memory to iomem resource */
index 538998a137d24e069969dcc3ed00cedc6c25616f..9ac639499bd1146347557141b10f1135ee2c0048 100644 (file)
@@ -21,7 +21,6 @@ static struct page *pcpu_chunk_page(struct pcpu_chunk *chunk,
 
 /**
  * pcpu_get_pages - get temp pages array
- * @chunk: chunk of interest
  *
  * Returns pointer to array of pointers to struct page which can be indexed
  * with pcpu_page_idx().  Note that there is only one array and accesses
@@ -30,7 +29,7 @@ static struct page *pcpu_chunk_page(struct pcpu_chunk *chunk,
  * RETURNS:
  * Pointer to temp pages array on success.
  */
-static struct page **pcpu_get_pages(struct pcpu_chunk *chunk_alloc)
+static struct page **pcpu_get_pages(void)
 {
        static struct page **pages;
        size_t pages_size = pcpu_nr_units * pcpu_unit_pages * sizeof(pages[0]);
@@ -275,7 +274,7 @@ static int pcpu_populate_chunk(struct pcpu_chunk *chunk,
 {
        struct page **pages;
 
-       pages = pcpu_get_pages(chunk);
+       pages = pcpu_get_pages();
        if (!pages)
                return -ENOMEM;
 
@@ -313,7 +312,7 @@ static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk,
         * successful population attempt so the temp pages array must
         * be available now.
         */
-       pages = pcpu_get_pages(chunk);
+       pages = pcpu_get_pages();
        BUG_ON(!pages);
 
        /* unmap and free */
index 5696039b5c0707eddcb652bc120a8556ca3cc58b..60a6488e9e6d49d5e9c5d4b611a5f5b037342316 100644 (file)
@@ -1011,8 +1011,11 @@ area_found:
                mutex_unlock(&pcpu_alloc_mutex);
        }
 
-       if (chunk != pcpu_reserved_chunk)
+       if (chunk != pcpu_reserved_chunk) {
+               spin_lock_irqsave(&pcpu_lock, flags);
                pcpu_nr_empty_pop_pages -= occ_pages;
+               spin_unlock_irqrestore(&pcpu_lock, flags);
+       }
 
        if (pcpu_nr_empty_pop_pages < PCPU_EMPTY_POP_PAGES_LOW)
                pcpu_schedule_balance_work();
index 9b5bc86f96ad731269e2051719583f168a74bc51..b1ccb58ad397403214a220e4a0ac7901a6b6ae1e 100644 (file)
@@ -267,8 +267,6 @@ int free_swap_slot(swp_entry_t entry)
 {
        struct swap_slots_cache *cache;
 
-       BUG_ON(!swap_slot_cache_initialized);
-
        cache = &get_cpu_var(swp_slots);
        if (use_swap_slot_cache && cache->slots_ret) {
                spin_lock_irq(&cache->free_lock);
index 0dd80222b20bbd6ab3c6235134e5f8f37b57815a..0b057628a7ba5c45d722710082ce32df3f7e8e13 100644 (file)
@@ -1683,7 +1683,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
 
                if (fatal_signal_pending(current)) {
                        area->nr_pages = i;
-                       goto fail;
+                       goto fail_no_warn;
                }
 
                if (node == NUMA_NO_NODE)
@@ -1709,6 +1709,7 @@ fail:
        warn_alloc(gfp_mask, NULL,
                          "vmalloc: allocation failure, allocated %ld of %ld bytes",
                          (area->nr_pages*PAGE_SIZE), area->size);
+fail_no_warn:
        vfree(area->addr);
        return NULL;
 }
index 8970a2fd3b1a5354fb4bc843292a1c7358eed51c..f9492bccfd794a1983eabbc4bff32df35b31cea8 100644 (file)
@@ -667,6 +667,7 @@ next:
                        z3fold_page_unlock(zhdr);
                        spin_lock(&pool->lock);
                        if (kref_put(&zhdr->refcount, release_z3fold_page)) {
+                               spin_unlock(&pool->lock);
                                atomic64_dec(&pool->pages_nr);
                                return 0;
                        }
index db9794ec61d88efe16419a6c4534daf7c8770bc1..5589de7086af4eca7634e786918600a81cf6b09c 100644 (file)
@@ -318,7 +318,8 @@ out:
        return error;
 }
 
-static int svc_accept(struct socket *sock, struct socket *newsock, int flags)
+static int svc_accept(struct socket *sock, struct socket *newsock, int flags,
+                     bool kern)
 {
        struct sock *sk = sock->sk;
        struct sk_buff *skb;
@@ -329,7 +330,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags)
 
        lock_sock(sk);
 
-       error = svc_create(sock_net(sk), newsock, 0, 0);
+       error = svc_create(sock_net(sk), newsock, 0, kern);
        if (error)
                goto out;
 
index a8e42cedf1dbc7e11a5803a3dbe857e1e4cd54e1..b7c486752b3acf64b821ccb8b0e1a9bc25c945da 100644 (file)
@@ -1320,7 +1320,8 @@ out_release:
        return err;
 }
 
-static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
+static int ax25_accept(struct socket *sock, struct socket *newsock, int flags,
+                      bool kern)
 {
        struct sk_buff *skb;
        struct sock *newsk;
index 7c3d994e90d87b868f2b1614cc5d26e2413e70ee..71343d0fec94b55f7318ec8578abc956148f7791 100644 (file)
@@ -2477,6 +2477,16 @@ static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface)
        batadv_iv_ogm_schedule(hard_iface);
 }
 
+/**
+ * batadv_iv_init_sel_class - initialize GW selection class
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv)
+{
+       /* set default TQ difference threshold to 20 */
+       atomic_set(&bat_priv->gw.sel_class, 20);
+}
+
 static struct batadv_gw_node *
 batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 {
@@ -2823,6 +2833,7 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
                .del_if = batadv_iv_ogm_orig_del_if,
        },
        .gw = {
+               .init_sel_class = batadv_iv_init_sel_class,
                .get_best_gw_node = batadv_iv_gw_get_best_gw_node,
                .is_eligible = batadv_iv_gw_is_eligible,
 #ifdef CONFIG_BATMAN_ADV_DEBUGFS
index 0acd081dd286996444d121b526f4530c4c1c0845..a36c8e7291d61f171cdb128dee865739d22cb00e 100644 (file)
@@ -668,6 +668,16 @@ err_ifinfo1:
        return ret;
 }
 
+/**
+ * batadv_v_init_sel_class - initialize GW selection class
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_v_init_sel_class(struct batadv_priv *bat_priv)
+{
+       /* set default throughput difference threshold to 5Mbps */
+       atomic_set(&bat_priv->gw.sel_class, 50);
+}
+
 static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv,
                                        char *buff, size_t count)
 {
@@ -1052,6 +1062,7 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = {
                .dump = batadv_v_orig_dump,
        },
        .gw = {
+               .init_sel_class = batadv_v_init_sel_class,
                .store_sel_class = batadv_v_store_sel_class,
                .show_sel_class = batadv_v_show_sel_class,
                .get_best_gw_node = batadv_v_gw_get_best_gw_node,
@@ -1092,9 +1103,6 @@ int batadv_v_mesh_init(struct batadv_priv *bat_priv)
        if (ret < 0)
                return ret;
 
-       /* set default throughput difference threshold to 5Mbps */
-       atomic_set(&bat_priv->gw.sel_class, 50);
-
        return 0;
 }
 
index 11a23fd6e1a07fa0c541fa3ea0a13775f9933893..8f964beaac284905c487ecfc5babaf2dd72d822c 100644 (file)
@@ -404,7 +404,7 @@ out:
  * batadv_frag_create - create a fragment from skb
  * @skb: skb to create fragment from
  * @frag_head: header to use in new fragment
- * @mtu: size of new fragment
+ * @fragment_size: size of new fragment
  *
  * Split the passed skb into two fragments: A new one with size matching the
  * passed mtu and the old one with the rest. The new skb contains data from the
@@ -414,11 +414,11 @@ out:
  */
 static struct sk_buff *batadv_frag_create(struct sk_buff *skb,
                                          struct batadv_frag_packet *frag_head,
-                                         unsigned int mtu)
+                                         unsigned int fragment_size)
 {
        struct sk_buff *skb_fragment;
        unsigned int header_size = sizeof(*frag_head);
-       unsigned int fragment_size = mtu - header_size;
+       unsigned int mtu = fragment_size + header_size;
 
        skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN);
        if (!skb_fragment)
@@ -456,7 +456,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
        struct sk_buff *skb_fragment;
        unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;
        unsigned int header_size = sizeof(frag_header);
-       unsigned int max_fragment_size, max_packet_size;
+       unsigned int max_fragment_size, num_fragments;
        int ret;
 
        /* To avoid merge and refragmentation at next-hops we never send
@@ -464,10 +464,15 @@ int batadv_frag_send_packet(struct sk_buff *skb,
         */
        mtu = min_t(unsigned int, mtu, BATADV_FRAG_MAX_FRAG_SIZE);
        max_fragment_size = mtu - header_size;
-       max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS;
+
+       if (skb->len == 0 || max_fragment_size == 0)
+               return -EINVAL;
+
+       num_fragments = (skb->len - 1) / max_fragment_size + 1;
+       max_fragment_size = (skb->len - 1) / num_fragments + 1;
 
        /* Don't even try to fragment, if we need more than 16 fragments */
-       if (skb->len > max_packet_size) {
+       if (num_fragments > BATADV_FRAG_MAX_FRAGMENTS) {
                ret = -EAGAIN;
                goto free_skb;
        }
@@ -507,7 +512,8 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                        goto put_primary_if;
                }
 
-               skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
+               skb_fragment = batadv_frag_create(skb, &frag_header,
+                                                 max_fragment_size);
                if (!skb_fragment) {
                        ret = -ENOMEM;
                        goto put_primary_if;
index 5db2e43e3775ef40fc3832984c93411c7f0dbb08..33940c5c74a8730c4ed3e06f7246e022cfb798da 100644 (file)
@@ -253,6 +253,11 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
  */
 void batadv_gw_init(struct batadv_priv *bat_priv)
 {
+       if (bat_priv->algo_ops->gw.init_sel_class)
+               bat_priv->algo_ops->gw.init_sel_class(bat_priv);
+       else
+               atomic_set(&bat_priv->gw.sel_class, 1);
+
        batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1,
                                     NULL, BATADV_TVLV_GW, 1,
                                     BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
index 5d099b2e6cfccb8a436d98a10a6d513d89e31dc1..d042c99af028e2083307de1ba8978f2061fee45d 100644 (file)
@@ -819,7 +819,6 @@ static int batadv_softif_init_late(struct net_device *dev)
        atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0);
 #endif
        atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF);
-       atomic_set(&bat_priv->gw.sel_class, 20);
        atomic_set(&bat_priv->gw.bandwidth_down, 100);
        atomic_set(&bat_priv->gw.bandwidth_up, 20);
        atomic_set(&bat_priv->orig_interval, 1000);
index 66b25e410a41375e5c70bd7400a5b353bdff4520..246f21b4973bc39d0678273ad831da1f5b7e0df3 100644 (file)
@@ -1489,6 +1489,7 @@ struct batadv_algo_orig_ops {
 
 /**
  * struct batadv_algo_gw_ops - mesh algorithm callbacks (GW specific)
+ * @init_sel_class: initialize GW selection class (optional)
  * @store_sel_class: parse and stores a new GW selection class (optional)
  * @show_sel_class: prints the current GW selection class (optional)
  * @get_best_gw_node: select the best GW from the list of available nodes
@@ -1499,6 +1500,7 @@ struct batadv_algo_orig_ops {
  * @dump: dump gateways to a netlink socket (optional)
  */
 struct batadv_algo_gw_ops {
+       void (*init_sel_class)(struct batadv_priv *bat_priv);
        ssize_t (*store_sel_class)(struct batadv_priv *bat_priv, char *buff,
                                   size_t count);
        ssize_t (*show_sel_class)(struct batadv_priv *bat_priv, char *buff);
index f307b145ea5405482434a9c37cafeb6d3f32dee4..507b80d59dec4fd3b0eb3c50ed1cd95a78adfcb7 100644 (file)
@@ -301,7 +301,7 @@ done:
 }
 
 static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
-                            int flags)
+                            int flags, bool kern)
 {
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
        struct sock *sk = sock->sk, *nsk;
index aa1a814ceddca77f790f0c570e9c89ef08ebe186..ac3c650cb234f9985ddf0b54924db9000c4586c3 100644 (file)
@@ -471,7 +471,8 @@ done:
        return err;
 }
 
-static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags,
+                             bool kern)
 {
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
        struct sock *sk = sock->sk, *nsk;
index e4e9a2da1e7e7a0e4b9764fe6de8819b9908ef3f..728e0c8dc8e74ccb134b8ed1d493ea8ee49bf49b 100644 (file)
@@ -627,7 +627,7 @@ done:
 }
 
 static int sco_sock_accept(struct socket *sock, struct socket *newsock,
-                          int flags)
+                          int flags, bool kern)
 {
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
        struct sock *sk = sock->sk, *ch;
index 4f598dc2d9168cd323a3027d77d601854aa35f04..6e08b7199dd7442acdbd4f85e5ef6315b121ca06 100644 (file)
@@ -106,7 +106,7 @@ static struct net_bridge_fdb_entry *br_fdb_find(struct net_bridge *br,
        struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
        struct net_bridge_fdb_entry *fdb;
 
-       WARN_ON_ONCE(!br_hash_lock_held(br));
+       lockdep_assert_held_once(&br->hash_lock);
 
        rcu_read_lock();
        fdb = fdb_find_rcu(head, addr, vid);
index 236f34244dbe1f2cd2bdfaf9d4eceb0765276882..013f2290bfa56df90708879437a762c812dec101 100644 (file)
@@ -30,6 +30,7 @@ EXPORT_SYMBOL(br_should_route_hook);
 static int
 br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       br_drop_fake_rtable(skb);
        return netif_receive_skb(skb);
 }
 
index 95087e6e8258366af95579bb308d1a6e18266f0e..1f1e62095464f99eaca8de49a772289f057bd943 100644 (file)
@@ -521,21 +521,6 @@ static unsigned int br_nf_pre_routing(void *priv,
 }
 
 
-/* PF_BRIDGE/LOCAL_IN ************************************************/
-/* The packet is locally destined, which requires a real
- * dst_entry, so detach the fake one.  On the way up, the
- * packet would pass through PRE_ROUTING again (which already
- * took place when the packet entered the bridge), but we
- * register an IPv4 PRE_ROUTING 'sabotage' hook that will
- * prevent this from happening. */
-static unsigned int br_nf_local_in(void *priv,
-                                  struct sk_buff *skb,
-                                  const struct nf_hook_state *state)
-{
-       br_drop_fake_rtable(skb);
-       return NF_ACCEPT;
-}
-
 /* PF_BRIDGE/FORWARD *************************************************/
 static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
@@ -721,18 +706,20 @@ static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
 
 static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
-       struct nf_bridge_info *nf_bridge;
-       unsigned int mtu_reserved;
+       struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+       unsigned int mtu, mtu_reserved;
 
        mtu_reserved = nf_bridge_mtu_reduction(skb);
+       mtu = skb->dev->mtu;
 
-       if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) {
+       if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu)
+               mtu = nf_bridge->frag_max_size;
+
+       if (skb_is_gso(skb) || skb->len + mtu_reserved <= mtu) {
                nf_bridge_info_free(skb);
                return br_dev_queue_push_xmit(net, sk, skb);
        }
 
-       nf_bridge = nf_bridge_info_get(skb);
-
        /* This is wrong! We should preserve the original fragment
         * boundaries by preserving frag_list rather than refragmenting.
         */
@@ -907,12 +894,6 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = {
                .hooknum = NF_BR_PRE_ROUTING,
                .priority = NF_BR_PRI_BRNF,
        },
-       {
-               .hook = br_nf_local_in,
-               .pf = NFPROTO_BRIDGE,
-               .hooknum = NF_BR_LOCAL_IN,
-               .priority = NF_BR_PRI_BRNF,
-       },
        {
                .hook = br_nf_forward_ip,
                .pf = NFPROTO_BRIDGE,
index 2288fca7756c5103fc4e8420ad61a2f9e633c097..61368186edea53841b1f00b37ddaa0d26461aee3 100644 (file)
@@ -531,15 +531,6 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
                              const unsigned char *addr, u16 vid);
 
-static inline bool br_hash_lock_held(struct net_bridge *br)
-{
-#ifdef CONFIG_LOCKDEP
-       return lockdep_is_held(&br->hash_lock);
-#else
-       return true;
-#endif
-}
-
 /* br_forward.c */
 enum br_pkt_type {
        BR_PKT_UNICAST,
index 38dcf1eb427de562776934b1c2dfff2c46f3ca12..f76bb333261384257490b0f5125207028e8352aa 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/kthread.h>
 #include <linux/net.h>
 #include <linux/nsproxy.h>
+#include <linux/sched/mm.h>
 #include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/string.h>
@@ -469,11 +470,16 @@ static int ceph_tcp_connect(struct ceph_connection *con)
 {
        struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
        struct socket *sock;
+       unsigned int noio_flag;
        int ret;
 
        BUG_ON(con->sock);
+
+       /* sock_create_kern() allocates with GFP_KERNEL */
+       noio_flag = memalloc_noio_save();
        ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family,
                               SOCK_STREAM, IPPROTO_TCP, &sock);
+       memalloc_noio_restore(noio_flag);
        if (ret)
                return ret;
        sock->sk->sk_allocation = GFP_NOFS;
index 8637b2b71f3d4751366a2ca5ba46579e6a5fa953..7869ae3837ca741e344b1731dc50d8408d8bcb6c 100644 (file)
@@ -1304,6 +1304,7 @@ void netdev_notify_peers(struct net_device *dev)
 {
        rtnl_lock();
        call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
+       call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev);
        rtnl_unlock();
 }
 EXPORT_SYMBOL(netdev_notify_peers);
index 3945821e9c1f8f8c33290e55d33aba28ff68a9cd..65ea0ff4017c166fea648f3ef3db57966f44aa66 100644 (file)
@@ -953,7 +953,7 @@ net_rx_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
        while (--i >= new_num) {
                struct kobject *kobj = &dev->_rx[i].kobj;
 
-               if (!list_empty(&dev_net(dev)->exit_list))
+               if (!atomic_read(&dev_net(dev)->count))
                        kobj->uevent_suppress = 1;
                if (dev->sysfs_rx_queue_group)
                        sysfs_remove_group(kobj, dev->sysfs_rx_queue_group);
@@ -1371,7 +1371,7 @@ netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
        while (--i >= new_num) {
                struct netdev_queue *queue = dev->_tx + i;
 
-               if (!list_empty(&dev_net(dev)->exit_list))
+               if (!atomic_read(&dev_net(dev)->count))
                        queue->kobj.uevent_suppress = 1;
 #ifdef CONFIG_BQL
                sysfs_remove_group(&queue->kobj, &dql_group);
@@ -1558,7 +1558,7 @@ void netdev_unregister_kobject(struct net_device *ndev)
 {
        struct device *dev = &(ndev->dev);
 
-       if (!list_empty(&dev_net(ndev)->exit_list))
+       if (!atomic_read(&dev_net(ndev)->count))
                dev_set_uevent_suppress(dev, 1);
 
        kobject_get(&dev->kobj);
index 6ae56037bb1336d9cb6b6fc36043a203f3978202..029a61ac6cdd8a0b4dd54d2be3c5bdf047a82cb0 100644 (file)
@@ -71,27 +71,17 @@ static int update_classid_sock(const void *v, struct file *file, unsigned n)
        return 0;
 }
 
-static void update_classid(struct cgroup_subsys_state *css, void *v)
+static void cgrp_attach(struct cgroup_taskset *tset)
 {
-       struct css_task_iter it;
+       struct cgroup_subsys_state *css;
        struct task_struct *p;
 
-       css_task_iter_start(css, &it);
-       while ((p = css_task_iter_next(&it))) {
+       cgroup_taskset_for_each(p, css, tset) {
                task_lock(p);
-               iterate_fd(p->files, 0, update_classid_sock, v);
+               iterate_fd(p->files, 0, update_classid_sock,
+                          (void *)(unsigned long)css_cls_state(css)->classid);
                task_unlock(p);
        }
-       css_task_iter_end(&it);
-}
-
-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);
 }
 
 static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
@@ -103,12 +93,22 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
                         u64 value)
 {
        struct cgroup_cls_state *cs = css_cls_state(css);
+       struct css_task_iter it;
+       struct task_struct *p;
 
        cgroup_sk_alloc_disable();
 
        cs->classid = (u32)value;
 
-       update_classid(css, (void *)(unsigned long)cs->classid);
+       css_task_iter_start(css, &it);
+       while ((p = css_task_iter_next(&it))) {
+               task_lock(p);
+               iterate_fd(p->files, 0, update_classid_sock,
+                          (void *)(unsigned long)cs->classid);
+               task_unlock(p);
+       }
+       css_task_iter_end(&it);
+
        return 0;
 }
 
index f3557958e9bf147631a90b51fef0630920acd97b..9f781092fda9cb8cac22b0743b4bc7666a3bd91a 100644 (file)
@@ -3694,6 +3694,15 @@ static void sock_rmem_free(struct sk_buff *skb)
        atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 }
 
+static void skb_set_err_queue(struct sk_buff *skb)
+{
+       /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING.
+        * So, it is safe to (mis)use it to mark skbs on the error queue.
+        */
+       skb->pkt_type = PACKET_OUTGOING;
+       BUILD_BUG_ON(PACKET_OUTGOING == 0);
+}
+
 /*
  * Note: We dont mem charge error packets (no sk_forward_alloc changes)
  */
@@ -3707,6 +3716,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
        skb->sk = sk;
        skb->destructor = sock_rmem_free;
        atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+       skb_set_err_queue(skb);
 
        /* before exiting rcu section, make sure dst is refcounted */
        skb_dst_force(skb);
@@ -3783,16 +3793,20 @@ EXPORT_SYMBOL(skb_clone_sk);
 
 static void __skb_complete_tx_timestamp(struct sk_buff *skb,
                                        struct sock *sk,
-                                       int tstype)
+                                       int tstype,
+                                       bool opt_stats)
 {
        struct sock_exterr_skb *serr;
        int err;
 
+       BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb));
+
        serr = SKB_EXT_ERR(skb);
        memset(serr, 0, sizeof(*serr));
        serr->ee.ee_errno = ENOMSG;
        serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
        serr->ee.ee_info = tstype;
+       serr->opt_stats = opt_stats;
        if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
                serr->ee.ee_data = skb_shinfo(skb)->tskey;
                if (sk->sk_protocol == IPPROTO_TCP &&
@@ -3828,13 +3842,14 @@ void skb_complete_tx_timestamp(struct sk_buff *skb,
        if (!skb_may_tx_timestamp(sk, false))
                return;
 
-       /* take a reference to prevent skb_orphan() from freeing the socket */
-       sock_hold(sk);
-
-       *skb_hwtstamps(skb) = *hwtstamps;
-       __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
-
-       sock_put(sk);
+       /* Take a reference to prevent skb_orphan() from freeing the socket,
+        * but only if the socket refcount is not zero.
+        */
+       if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) {
+               *skb_hwtstamps(skb) = *hwtstamps;
+               __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false);
+               sock_put(sk);
+       }
 }
 EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
 
@@ -3843,7 +3858,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
                     struct sock *sk, int tstype)
 {
        struct sk_buff *skb;
-       bool tsonly;
+       bool tsonly, opt_stats = false;
 
        if (!sk)
                return;
@@ -3856,9 +3871,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
 #ifdef CONFIG_INET
                if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
                    sk->sk_protocol == IPPROTO_TCP &&
-                   sk->sk_type == SOCK_STREAM)
+                   sk->sk_type == SOCK_STREAM) {
                        skb = tcp_get_timestamping_opt_stats(sk);
-               else
+                       opt_stats = true;
+               } else
 #endif
                        skb = alloc_skb(0, GFP_ATOMIC);
        } else {
@@ -3877,7 +3893,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
        else
                skb->tstamp = ktime_get_real();
 
-       __skb_complete_tx_timestamp(skb, sk, tstype);
+       __skb_complete_tx_timestamp(skb, sk, tstype, opt_stats);
 }
 EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
 
@@ -3893,7 +3909,7 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
 {
        struct sock *sk = skb->sk;
        struct sock_exterr_skb *serr;
-       int err;
+       int err = 1;
 
        skb->wifi_acked_valid = 1;
        skb->wifi_acked = acked;
@@ -3903,14 +3919,15 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
        serr->ee.ee_errno = ENOMSG;
        serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
 
-       /* take a reference to prevent skb_orphan() from freeing the socket */
-       sock_hold(sk);
-
-       err = sock_queue_err_skb(sk, skb);
+       /* Take a reference to prevent skb_orphan() from freeing the socket,
+        * but only if the socket refcount is not zero.
+        */
+       if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) {
+               err = sock_queue_err_skb(sk, skb);
+               sock_put(sk);
+       }
        if (err)
                kfree_skb(skb);
-
-       sock_put(sk);
 }
 EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
 
index f6fd79f33097f3fa279fcb0b610286259af9b111..2c4f574168fbdcebc0cc82c0c8a36214992d6224 100644 (file)
@@ -197,66 +197,55 @@ EXPORT_SYMBOL(sk_net_capable);
 
 /*
  * Each address family might have different locking rules, so we have
- * one slock key per address family:
+ * one slock key per address family and separate keys for internal and
+ * userspace sockets.
  */
 static struct lock_class_key af_family_keys[AF_MAX];
+static struct lock_class_key af_family_kern_keys[AF_MAX];
 static struct lock_class_key af_family_slock_keys[AF_MAX];
+static struct lock_class_key af_family_kern_slock_keys[AF_MAX];
 
 /*
  * Make lock validator output more readable. (we pre-construct these
  * strings build-time, so that runtime initialization of socket
  * locks is fast):
  */
+
+#define _sock_locks(x)                                           \
+  x "AF_UNSPEC",       x "AF_UNIX"     ,       x "AF_INET"     , \
+  x "AF_AX25"  ,       x "AF_IPX"      ,       x "AF_APPLETALK", \
+  x "AF_NETROM",       x "AF_BRIDGE"   ,       x "AF_ATMPVC"   , \
+  x "AF_X25"   ,       x "AF_INET6"    ,       x "AF_ROSE"     , \
+  x "AF_DECnet",       x "AF_NETBEUI"  ,       x "AF_SECURITY" , \
+  x "AF_KEY"   ,       x "AF_NETLINK"  ,       x "AF_PACKET"   , \
+  x "AF_ASH"   ,       x "AF_ECONET"   ,       x "AF_ATMSVC"   , \
+  x "AF_RDS"   ,       x "AF_SNA"      ,       x "AF_IRDA"     , \
+  x "AF_PPPOX" ,       x "AF_WANPIPE"  ,       x "AF_LLC"      , \
+  x "27"       ,       x "28"          ,       x "AF_CAN"      , \
+  x "AF_TIPC"  ,       x "AF_BLUETOOTH",       x "IUCV"        , \
+  x "AF_RXRPC" ,       x "AF_ISDN"     ,       x "AF_PHONET"   , \
+  x "AF_IEEE802154",   x "AF_CAIF"     ,       x "AF_ALG"      , \
+  x "AF_NFC"   ,       x "AF_VSOCK"    ,       x "AF_KCM"      , \
+  x "AF_QIPCRTR",      x "AF_SMC"      ,       x "AF_MAX"
+
 static const char *const af_family_key_strings[AF_MAX+1] = {
-  "sk_lock-AF_UNSPEC", "sk_lock-AF_UNIX"     , "sk_lock-AF_INET"     ,
-  "sk_lock-AF_AX25"  , "sk_lock-AF_IPX"      , "sk_lock-AF_APPLETALK",
-  "sk_lock-AF_NETROM", "sk_lock-AF_BRIDGE"   , "sk_lock-AF_ATMPVC"   ,
-  "sk_lock-AF_X25"   , "sk_lock-AF_INET6"    , "sk_lock-AF_ROSE"     ,
-  "sk_lock-AF_DECnet", "sk_lock-AF_NETBEUI"  , "sk_lock-AF_SECURITY" ,
-  "sk_lock-AF_KEY"   , "sk_lock-AF_NETLINK"  , "sk_lock-AF_PACKET"   ,
-  "sk_lock-AF_ASH"   , "sk_lock-AF_ECONET"   , "sk_lock-AF_ATMSVC"   ,
-  "sk_lock-AF_RDS"   , "sk_lock-AF_SNA"      , "sk_lock-AF_IRDA"     ,
-  "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE"  , "sk_lock-AF_LLC"      ,
-  "sk_lock-27"       , "sk_lock-28"          , "sk_lock-AF_CAN"      ,
-  "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
-  "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
-  "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
-  "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_KCM"      ,
-  "sk_lock-AF_QIPCRTR", "sk_lock-AF_SMC"     , "sk_lock-AF_MAX"
+       _sock_locks("sk_lock-")
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
-  "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
-  "slock-AF_AX25"  , "slock-AF_IPX"      , "slock-AF_APPLETALK",
-  "slock-AF_NETROM", "slock-AF_BRIDGE"   , "slock-AF_ATMPVC"   ,
-  "slock-AF_X25"   , "slock-AF_INET6"    , "slock-AF_ROSE"     ,
-  "slock-AF_DECnet", "slock-AF_NETBEUI"  , "slock-AF_SECURITY" ,
-  "slock-AF_KEY"   , "slock-AF_NETLINK"  , "slock-AF_PACKET"   ,
-  "slock-AF_ASH"   , "slock-AF_ECONET"   , "slock-AF_ATMSVC"   ,
-  "slock-AF_RDS"   , "slock-AF_SNA"      , "slock-AF_IRDA"     ,
-  "slock-AF_PPPOX" , "slock-AF_WANPIPE"  , "slock-AF_LLC"      ,
-  "slock-27"       , "slock-28"          , "slock-AF_CAN"      ,
-  "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
-  "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
-  "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
-  "slock-AF_NFC"   , "slock-AF_VSOCK"    ,"slock-AF_KCM"       ,
-  "slock-AF_QIPCRTR", "slock-AF_SMC"     , "slock-AF_MAX"
+       _sock_locks("slock-")
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
-  "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
-  "clock-AF_AX25"  , "clock-AF_IPX"      , "clock-AF_APPLETALK",
-  "clock-AF_NETROM", "clock-AF_BRIDGE"   , "clock-AF_ATMPVC"   ,
-  "clock-AF_X25"   , "clock-AF_INET6"    , "clock-AF_ROSE"     ,
-  "clock-AF_DECnet", "clock-AF_NETBEUI"  , "clock-AF_SECURITY" ,
-  "clock-AF_KEY"   , "clock-AF_NETLINK"  , "clock-AF_PACKET"   ,
-  "clock-AF_ASH"   , "clock-AF_ECONET"   , "clock-AF_ATMSVC"   ,
-  "clock-AF_RDS"   , "clock-AF_SNA"      , "clock-AF_IRDA"     ,
-  "clock-AF_PPPOX" , "clock-AF_WANPIPE"  , "clock-AF_LLC"      ,
-  "clock-27"       , "clock-28"          , "clock-AF_CAN"      ,
-  "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
-  "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
-  "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
-  "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_KCM"      ,
-  "clock-AF_QIPCRTR", "clock-AF_SMC"     , "clock-AF_MAX"
+       _sock_locks("clock-")
+};
+
+static const char *const af_family_kern_key_strings[AF_MAX+1] = {
+       _sock_locks("k-sk_lock-")
+};
+static const char *const af_family_kern_slock_key_strings[AF_MAX+1] = {
+       _sock_locks("k-slock-")
+};
+static const char *const af_family_kern_clock_key_strings[AF_MAX+1] = {
+       _sock_locks("k-clock-")
 };
 
 /*
@@ -264,6 +253,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
  * so split the lock classes by using a per-AF key:
  */
 static struct lock_class_key af_callback_keys[AF_MAX];
+static struct lock_class_key af_kern_callback_keys[AF_MAX];
 
 /* Take into consideration the size of the struct sk_buff overhead in the
  * determination of these values, since that is non-constant across
@@ -1293,7 +1283,16 @@ lenout:
  */
 static inline void sock_lock_init(struct sock *sk)
 {
-       sock_lock_init_class_and_name(sk,
+       if (sk->sk_kern_sock)
+               sock_lock_init_class_and_name(
+                       sk,
+                       af_family_kern_slock_key_strings[sk->sk_family],
+                       af_family_kern_slock_keys + sk->sk_family,
+                       af_family_kern_key_strings[sk->sk_family],
+                       af_family_kern_keys + sk->sk_family);
+       else
+               sock_lock_init_class_and_name(
+                       sk,
                        af_family_slock_key_strings[sk->sk_family],
                        af_family_slock_keys + sk->sk_family,
                        af_family_key_strings[sk->sk_family],
@@ -1399,6 +1398,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
                 * why we need sk_prot_creator -acme
                 */
                sk->sk_prot = sk->sk_prot_creator = prot;
+               sk->sk_kern_sock = kern;
                sock_lock_init(sk);
                sk->sk_net_refcnt = kern ? 0 : 1;
                if (likely(sk->sk_net_refcnt))
@@ -1442,6 +1442,11 @@ static void __sk_destruct(struct rcu_head *head)
                pr_debug("%s: optmem leakage (%d bytes) detected\n",
                         __func__, atomic_read(&sk->sk_omem_alloc));
 
+       if (sk->sk_frag.page) {
+               put_page(sk->sk_frag.page);
+               sk->sk_frag.page = NULL;
+       }
+
        if (sk->sk_peer_cred)
                put_cred(sk->sk_peer_cred);
        put_pid(sk->sk_peer_pid);
@@ -1539,6 +1544,12 @@ 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, sk))) {
+                       /* We need to make sure that we don't uncharge the new
+                        * socket if we couldn't charge it in the first place
+                        * as otherwise we uncharge the parent's filter.
+                        */
+                       if (!is_charged)
+                               RCU_INIT_POINTER(newsk->sk_filter, NULL);
                        sk_free_unlock_clone(newsk);
                        newsk = NULL;
                        goto out;
@@ -2277,7 +2288,8 @@ int sock_no_socketpair(struct socket *sock1, struct socket *sock2)
 }
 EXPORT_SYMBOL(sock_no_socketpair);
 
-int sock_no_accept(struct socket *sock, struct socket *newsock, int flags)
+int sock_no_accept(struct socket *sock, struct socket *newsock, int flags,
+                  bool kern)
 {
        return -EOPNOTSUPP;
 }
@@ -2481,7 +2493,14 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        }
 
        rwlock_init(&sk->sk_callback_lock);
-       lockdep_set_class_and_name(&sk->sk_callback_lock,
+       if (sk->sk_kern_sock)
+               lockdep_set_class_and_name(
+                       &sk->sk_callback_lock,
+                       af_kern_callback_keys + sk->sk_family,
+                       af_family_kern_clock_key_strings[sk->sk_family]);
+       else
+               lockdep_set_class_and_name(
+                       &sk->sk_callback_lock,
                        af_callback_keys + sk->sk_family,
                        af_family_clock_key_strings[sk->sk_family]);
 
@@ -2779,11 +2798,6 @@ void sk_common_release(struct sock *sk)
 
        sk_refcnt_debug_release(sk);
 
-       if (sk->sk_frag.page) {
-               put_page(sk->sk_frag.page);
-               sk->sk_frag.page = NULL;
-       }
-
        sock_put(sk);
 }
 EXPORT_SYMBOL(sk_common_release);
index f053198e730c48c7ea8114706c3d4904228f41fb..5e3a7302f7747e4c4f3134eacab2f2c65b13402f 100644 (file)
@@ -749,6 +749,7 @@ static void ccid2_hc_tx_exit(struct sock *sk)
        for (i = 0; i < hc->tx_seqbufc; i++)
                kfree(hc->tx_seqbuf[i]);
        hc->tx_seqbufc = 0;
+       dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
 }
 
 static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
index 409d0cfd34474812c3bf74f26cd423a3d65ee441..b99168b0fabf2a8c65defdd0b93d362630774e1a 100644 (file)
@@ -289,7 +289,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
 
        switch (type) {
        case ICMP_REDIRECT:
-               dccp_do_redirect(skb, sk);
+               if (!sock_owned_by_user(sk))
+                       dccp_do_redirect(skb, sk);
                goto out;
        case ICMP_SOURCE_QUENCH:
                /* Just silently ignore these. */
index 233b57367758c64c09ed40f7359cb8fcb1918d93..d9b6a4e403e701fd9b9ecf92bac496e45570054e 100644 (file)
@@ -122,10 +122,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        np = inet6_sk(sk);
 
        if (type == NDISC_REDIRECT) {
-               struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
+               if (!sock_owned_by_user(sk)) {
+                       struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
 
-               if (dst)
-                       dst->ops->redirect(dst, sk, skb);
+                       if (dst)
+                               dst->ops->redirect(dst, sk, skb);
+               }
                goto out;
        }
 
index e267e6f4c9a5566b369a03a600a408e5bd41cbad..abd07a443219853b022bef41cb072e90ff8f07f0 100644 (file)
@@ -142,6 +142,13 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
        struct dccp_request_sock *dreq = dccp_rsk(req);
        bool own_req;
 
+       /* TCP/DCCP listeners became lockless.
+        * DCCP stores complex state in its request_sock, so we need
+        * a protection for them, now this code runs without being protected
+        * by the parent (listener) lock.
+        */
+       spin_lock_bh(&dreq->dreq_lock);
+
        /* Check for retransmitted REQUEST */
        if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
 
@@ -156,7 +163,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
                        inet_rtx_syn_ack(sk, req);
                }
                /* Network Duplicate, discard packet */
-               return NULL;
+               goto out;
        }
 
        DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
@@ -182,20 +189,20 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
 
        child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
                                                         req, &own_req);
-       if (!child)
-               goto listen_overflow;
-
-       return inet_csk_complete_hashdance(sk, child, req, own_req);
+       if (child) {
+               child = inet_csk_complete_hashdance(sk, child, req, own_req);
+               goto out;
+       }
 
-listen_overflow:
-       dccp_pr_debug("listen_overflow!\n");
        DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
 drop:
        if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
                req->rsk_ops->send_reset(sk, skb);
 
        inet_csk_reqsk_queue_drop(sk, req);
-       return NULL;
+out:
+       spin_unlock_bh(&dreq->dreq_lock);
+       return child;
 }
 
 EXPORT_SYMBOL_GPL(dccp_check_req);
@@ -246,6 +253,7 @@ int dccp_reqsk_init(struct request_sock *req,
 {
        struct dccp_request_sock *dreq = dccp_rsk(req);
 
+       spin_lock_init(&dreq->dreq_lock);
        inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport;
        inet_rsk(req)->ir_num      = ntohs(dccp_hdr(skb)->dccph_dport);
        inet_rsk(req)->acked       = 0;
index e6e79eda97636df6f6e0e6e914405381c3efeaaa..7de5b40a5d0d1245ad995877f779e0d87d1cf398 100644 (file)
@@ -1070,7 +1070,8 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
        return skb == NULL ? ERR_PTR(err) : skb;
 }
 
-static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
+static int dn_accept(struct socket *sock, struct socket *newsock, int flags,
+                    bool kern)
 {
        struct sock *sk = sock->sk, *newsk;
        struct sk_buff *skb = NULL;
@@ -1099,7 +1100,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
 
        cb = DN_SKB_CB(skb);
        sk->sk_ack_backlog--;
-       newsk = dn_alloc_sock(sock_net(sk), newsock, sk->sk_allocation, 0);
+       newsk = dn_alloc_sock(sock_net(sk), newsock, sk->sk_allocation, kern);
        if (newsk == NULL) {
                release_sock(sk);
                kfree_skb(skb);
index 602d40f43687c91db7250822439bacbe85318fa3..6b1fc6e4278ef4f1cba58412977918af31d73e62 100644 (file)
@@ -689,11 +689,12 @@ EXPORT_SYMBOL(inet_stream_connect);
  *     Accept a pending connection. The TCP layer now gives BSD semantics.
  */
 
-int inet_accept(struct socket *sock, struct socket *newsock, int flags)
+int inet_accept(struct socket *sock, struct socket *newsock, int flags,
+               bool kern)
 {
        struct sock *sk1 = sock->sk;
        int err = -EINVAL;
-       struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err);
+       struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err, kern);
 
        if (!sk2)
                goto do_err;
@@ -1487,8 +1488,10 @@ int inet_gro_complete(struct sk_buff *skb, int nhoff)
        int proto = iph->protocol;
        int err = -ENOSYS;
 
-       if (skb->encapsulation)
+       if (skb->encapsulation) {
+               skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IP));
                skb_set_inner_network_header(skb, nhoff);
+       }
 
        csum_replace2(&iph->check, iph->tot_len, newlen);
        iph->tot_len = newlen;
index 42bfd08109dd78ab509493e8d2205d72845bb3eb..8f2133ffc2ff1b94871408a5f934cb938d3462b5 100644 (file)
@@ -1083,7 +1083,8 @@ static void nl_fib_input(struct sk_buff *skb)
 
        net = sock_net(skb->sk);
        nlh = nlmsg_hdr(skb);
-       if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len ||
+       if (skb->len < nlmsg_total_size(sizeof(*frn)) ||
+           skb->len < nlh->nlmsg_len ||
            nlmsg_len(nlh) < sizeof(*frn))
                return;
 
index b4d5980ade3b584c444d0f0c6523f03a2f71f884..5e313c1ac94fc88eca5fe3a0e9e46e551e955ff0 100644 (file)
@@ -424,7 +424,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
 /*
  * This will accept the next outstanding connection.
  */
-struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
+struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct request_sock_queue *queue = &icsk->icsk_accept_queue;
index bbe7f72db9c157ba2d6c5292637c2f58ad39a123..b3cdeec85f1f2c612c362590e828f50596a5c247 100644 (file)
@@ -198,6 +198,7 @@ static void ip_expire(unsigned long arg)
        qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
        net = container_of(qp->q.net, struct net, ipv4.frags);
 
+       rcu_read_lock();
        spin_lock(&qp->q.lock);
 
        if (qp->q.flags & INET_FRAG_COMPLETE)
@@ -207,7 +208,7 @@ static void ip_expire(unsigned long arg)
        __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
 
        if (!inet_frag_evicting(&qp->q)) {
-               struct sk_buff *head = qp->q.fragments;
+               struct sk_buff *clone, *head = qp->q.fragments;
                const struct iphdr *iph;
                int err;
 
@@ -216,32 +217,40 @@ static void ip_expire(unsigned long arg)
                if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments)
                        goto out;
 
-               rcu_read_lock();
                head->dev = dev_get_by_index_rcu(net, qp->iif);
                if (!head->dev)
-                       goto out_rcu_unlock;
+                       goto out;
+
 
                /* skb has no dst, perform route lookup again */
                iph = ip_hdr(head);
                err = ip_route_input_noref(head, iph->daddr, iph->saddr,
                                           iph->tos, head->dev);
                if (err)
-                       goto out_rcu_unlock;
+                       goto out;
 
                /* Only an end host needs to send an ICMP
                 * "Fragment Reassembly Timeout" message, per RFC792.
                 */
                if (frag_expire_skip_icmp(qp->user) &&
                    (skb_rtable(head)->rt_type != RTN_LOCAL))
-                       goto out_rcu_unlock;
+                       goto out;
+
+               clone = skb_clone(head, GFP_ATOMIC);
 
                /* Send an ICMP "Fragment Reassembly Timeout" message. */
-               icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
-out_rcu_unlock:
-               rcu_read_unlock();
+               if (clone) {
+                       spin_unlock(&qp->q.lock);
+                       icmp_send(clone, ICMP_TIME_EXCEEDED,
+                                 ICMP_EXC_FRAGTIME, 0);
+                       consume_skb(clone);
+                       goto out_rcu_unlock;
+               }
        }
 out:
        spin_unlock(&qp->q.lock);
+out_rcu_unlock:
+       rcu_read_unlock();
        ipq_put(qp);
 }
 
index 737ce826d7ecfa040d07d7f8e8d6dedd01ca7330..7a3fd25e8913a99d0fcbb256bc9001f6f1d4dd6f 100644 (file)
@@ -966,7 +966,7 @@ static int __ip_append_data(struct sock *sk,
        cork->length += length;
        if ((((length + fragheaderlen) > mtu) || (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
-           (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len &&
+           (rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
            (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
                err = ip_ufo_append_data(sk, queue, getfrag, from, length,
                                         hh_len, fragheaderlen, transhdrlen,
index bc1486f2c0643355ddac067cb79f075cafd788d1..2e14ed11a35cfc83db845e972521b2e8894f97c6 100644 (file)
@@ -165,6 +165,10 @@ static unsigned int ipv4_conntrack_local(void *priv,
        if (skb->len < sizeof(struct iphdr) ||
            ip_hdrlen(skb) < sizeof(struct iphdr))
                return NF_ACCEPT;
+
+       if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */
+               return NF_ACCEPT;
+
        return nf_conntrack_in(state->net, PF_INET, state->hook, skb);
 }
 
index f8aad03d674b05008edb5b9883b3a26b2fa7461f..6f5e8d01b876933a68e5f6cf8b2a48f8c4e17262 100644 (file)
@@ -255,11 +255,6 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
        /* maniptype == SRC for postrouting. */
        enum nf_nat_manip_type maniptype = HOOK2MANIP(state->hook);
 
-       /* We never see fragments: conntrack defrags on pre-routing
-        * and local-out, and nf_nat_out protects post-routing.
-        */
-       NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb)));
-
        ct = nf_ct_get(skb, &ctinfo);
        /* Can't track?  It's not due to stress, or conntrack would
         * have dropped it.  Hence it's the user's responsibilty to
index a0ea8aad1bf150bcb9e8e0aa2e6b45a5347599e4..f18677277119305aeea043d81deb4e6ee7d20b7c 100644 (file)
@@ -26,10 +26,10 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
        memset(&range, 0, sizeof(range));
        range.flags = priv->flags;
        if (priv->sreg_proto_min) {
-               range.min_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_min];
-               range.max_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_max];
+               range.min_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_min]);
+               range.max_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_max]);
        }
        regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt),
                                                    &range, nft_out(pkt));
index 1650ed23c15dd00bb8e4bd741dc2d02d6cbf2c4e..5120be1d31185dd5c879419f8889d36ddb363591 100644 (file)
@@ -26,10 +26,10 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr,
 
        memset(&mr, 0, sizeof(mr));
        if (priv->sreg_proto_min) {
-               mr.range[0].min.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_min];
-               mr.range[0].max.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_max];
+               mr.range[0].min.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_min]);
+               mr.range[0].max.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_max]);
                mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
        }
 
index cf4555581282c608f920254078264e36e18584c6..1e319a525d51b0b603a5ccc5143381c752b9f2c7 100644 (file)
@@ -2770,7 +2770,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
 {
        const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */
        const struct inet_connection_sock *icsk = inet_csk(sk);
-       u32 now = tcp_time_stamp, intv;
+       u32 now, intv;
        u64 rate64;
        bool slow;
        u32 rate;
@@ -2839,6 +2839,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        info->tcpi_retrans = tp->retrans_out;
        info->tcpi_fackets = tp->fackets_out;
 
+       now = tcp_time_stamp;
        info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
        info->tcpi_last_data_recv = jiffies_to_msecs(now - icsk->icsk_ack.lrcvtime);
        info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
index 39c393cc0fd3c17130cd5d8d8b37f31ad3aeafd9..c43119726a62e494063fd940001b483215d0fe26 100644 (file)
@@ -5541,6 +5541,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
        struct inet_connection_sock *icsk = inet_csk(sk);
 
        tcp_set_state(sk, TCP_ESTABLISHED);
+       icsk->icsk_ack.lrcvtime = tcp_time_stamp;
 
        if (skb) {
                icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
@@ -5759,7 +5760,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                         * to stand against the temptation 8)     --ANK
                         */
                        inet_csk_schedule_ack(sk);
-                       icsk->icsk_ack.lrcvtime = tcp_time_stamp;
                        tcp_enter_quickack_mode(sk);
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
                                                  TCP_DELACK_MAX, TCP_RTO_MAX);
index 9a89b8deafae1e9b2e8d1d9bc211c9c30b8dd8ec..575e19dcc01763ef3fa938dea3ea51995b573163 100644 (file)
@@ -279,10 +279,13 @@ EXPORT_SYMBOL(tcp_v4_connect);
  */
 void tcp_v4_mtu_reduced(struct sock *sk)
 {
-       struct dst_entry *dst;
        struct inet_sock *inet = inet_sk(sk);
-       u32 mtu = tcp_sk(sk)->mtu_info;
+       struct dst_entry *dst;
+       u32 mtu;
 
+       if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
+               return;
+       mtu = tcp_sk(sk)->mtu_info;
        dst = inet_csk_update_pmtu(sk, mtu);
        if (!dst)
                return;
@@ -428,7 +431,8 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
 
        switch (type) {
        case ICMP_REDIRECT:
-               do_redirect(icmp_skb, sk);
+               if (!sock_owned_by_user(sk))
+                       do_redirect(icmp_skb, sk);
                goto out;
        case ICMP_SOURCE_QUENCH:
                /* Just silently ignore these. */
index 7e16243cdb58c830f869fe483730e86400e2eb00..65c0f3d13eca47c6394c09925decf54287d01b48 100644 (file)
@@ -460,6 +460,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
                newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
                minmax_reset(&newtp->rtt_min, tcp_time_stamp, ~0U);
                newicsk->icsk_rto = TCP_TIMEOUT_INIT;
+               newicsk->icsk_ack.lrcvtime = tcp_time_stamp;
 
                newtp->packets_out = 0;
                newtp->retrans_out = 0;
index 40d893556e6701ace6a02903e53c45822d6fa56d..b2ab411c6d3728fa7dbdebde045532a7317f5166 100644 (file)
@@ -249,7 +249,8 @@ void tcp_delack_timer_handler(struct sock *sk)
 
        sk_mem_reclaim_partial(sk);
 
-       if (sk->sk_state == TCP_CLOSE || !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
+       if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
+           !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
                goto out;
 
        if (time_after(icsk->icsk_ack.timeout, jiffies)) {
@@ -552,7 +553,8 @@ void tcp_write_timer_handler(struct sock *sk)
        struct inet_connection_sock *icsk = inet_csk(sk);
        int event;
 
-       if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending)
+       if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
+           !icsk->icsk_pending)
                goto out;
 
        if (time_after(icsk->icsk_timeout, jiffies)) {
index 04db40620ea65c1f369ef63490383e92def722ff..a9a9553ee63df8eb6e16e00d5da8c29406435350 100644 (file)
@@ -920,12 +920,12 @@ static int __init inet6_init(void)
        err = register_pernet_subsys(&inet6_net_ops);
        if (err)
                goto register_pernet_fail;
-       err = icmpv6_init();
-       if (err)
-               goto icmp_fail;
        err = ip6_mr_init();
        if (err)
                goto ipmr_fail;
+       err = icmpv6_init();
+       if (err)
+               goto icmp_fail;
        err = ndisc_init();
        if (err)
                goto ndisc_fail;
@@ -1061,10 +1061,10 @@ igmp_fail:
        ndisc_cleanup();
 ndisc_fail:
        ip6_mr_cleanup();
-ipmr_fail:
-       icmpv6_cleanup();
 icmp_fail:
        unregister_pernet_subsys(&inet6_net_ops);
+ipmr_fail:
+       icmpv6_cleanup();
 register_pernet_fail:
        sock_unregister(PF_INET6);
        rtnl_unregister_all(PF_INET6);
index e4266746e4a2af67562bb05dd50ace54e55d3edd..d4bf2c68a545b44873e433930e4e999920de78c9 100644 (file)
@@ -923,6 +923,8 @@ add:
                        ins = &rt->dst.rt6_next;
                        iter = *ins;
                        while (iter) {
+                               if (iter->rt6i_metric > rt->rt6i_metric)
+                                       break;
                                if (rt6_qualify_for_ecmp(iter)) {
                                        *ins = iter->dst.rt6_next;
                                        fib6_purge_rt(iter, fn, info->nl_net);
index 0838e6d01d2e4979559cae63a20ca339a3e2c22c..93e58a5e18374bee41f5a17f0c5911e381acb142 100644 (file)
@@ -294,8 +294,10 @@ static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
        struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + nhoff);
        int err = -ENOSYS;
 
-       if (skb->encapsulation)
+       if (skb->encapsulation) {
+               skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IPV6));
                skb_set_inner_network_header(skb, nhoff);
+       }
 
        iph->payload_len = htons(skb->len - nhoff - sizeof(*iph));
 
index 528b3c1f3fdee4314e1c23007ae76333b4af7505..58f6288e9ba53e6964b74d71dde7615ead695c06 100644 (file)
@@ -768,13 +768,14 @@ slow_path:
         *      Fragment the datagram.
         */
 
-       *prevhdr = NEXTHDR_FRAGMENT;
        troom = rt->dst.dev->needed_tailroom;
 
        /*
         *      Keep copying data until we run out.
         */
        while (left > 0)        {
+               u8 *fragnexthdr_offset;
+
                len = left;
                /* IF: it doesn't fit, use 'mtu' - the data space left */
                if (len > mtu)
@@ -819,6 +820,10 @@ slow_path:
                 */
                skb_copy_from_linear_data(skb, skb_network_header(frag), hlen);
 
+               fragnexthdr_offset = skb_network_header(frag);
+               fragnexthdr_offset += prevhdr - skb_network_header(skb);
+               *fragnexthdr_offset = NEXTHDR_FRAGMENT;
+
                /*
                 *      Build fragment header.
                 */
@@ -1385,7 +1390,7 @@ emsgsize:
        if ((((length + fragheaderlen) > mtu) ||
             (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
-           (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len &&
+           (rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
            (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) {
                err = ip6_ufo_append_data(sk, queue, getfrag, from, length,
                                          hh_len, fragheaderlen, exthdrlen,
index 644ba59fbd9d5ed8d6ba4a8082dd327589c9bb68..3d8a3b63b4fdbec7d488194e21e0c9013f0ff6da 100644 (file)
@@ -485,11 +485,15 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
        if (!skb->ignore_df && skb->len > mtu) {
                skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu);
 
-               if (skb->protocol == htons(ETH_P_IPV6))
+               if (skb->protocol == htons(ETH_P_IPV6)) {
+                       if (mtu < IPV6_MIN_MTU)
+                               mtu = IPV6_MIN_MTU;
+
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-               else
+               } else {
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
                                  htonl(mtu));
+               }
 
                return -EMSGSIZE;
        }
index 6c5b5b1830a74f52e2dbc4f4f2bb8127a0ba2efb..4146536e9c1517fc5e2e0ad066a8e87154446dda 100644 (file)
@@ -27,10 +27,10 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,
        memset(&range, 0, sizeof(range));
        range.flags = priv->flags;
        if (priv->sreg_proto_min) {
-               range.min_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_min];
-               range.max_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_max];
+               range.min_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_min]);
+               range.max_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_max]);
        }
        regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range,
                                                    nft_out(pkt));
index f5ac080fc0849b0f65751458432cf4e693353c8a..a27e424f690d699fafc5f2a7135637f36fb66388 100644 (file)
@@ -26,10 +26,10 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr,
 
        memset(&range, 0, sizeof(range));
        if (priv->sreg_proto_min) {
-               range.min_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_min],
-               range.max_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_max],
+               range.min_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_min]);
+               range.max_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_max]);
                range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
        }
 
index 229bfcc451ef5004e9e9d14c071937c1b9658711..9db1418993f2b8a5b4194895f243441033d4729a 100644 (file)
@@ -3299,7 +3299,6 @@ static size_t rt6_nlmsg_size(struct rt6_info *rt)
                nexthop_len = nla_total_size(0)  /* RTA_MULTIPATH */
                            + NLA_ALIGN(sizeof(struct rtnexthop))
                            + nla_total_size(16) /* RTA_GATEWAY */
-                           + nla_total_size(4)  /* RTA_OIF */
                            + lwtunnel_get_encap_size(rt->dst.lwtstate);
 
                nexthop_len *= rt->rt6i_nsiblings;
@@ -3323,7 +3322,7 @@ static size_t rt6_nlmsg_size(struct rt6_info *rt)
 }
 
 static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
-                           unsigned int *flags)
+                           unsigned int *flags, bool skip_oif)
 {
        if (!netif_running(rt->dst.dev) || !netif_carrier_ok(rt->dst.dev)) {
                *flags |= RTNH_F_LINKDOWN;
@@ -3336,7 +3335,8 @@ static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
                        goto nla_put_failure;
        }
 
-       if (rt->dst.dev &&
+       /* not needed for multipath encoding b/c it has a rtnexthop struct */
+       if (!skip_oif && rt->dst.dev &&
            nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
                goto nla_put_failure;
 
@@ -3350,6 +3350,7 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+/* add multipath next hop */
 static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
 {
        struct rtnexthop *rtnh;
@@ -3362,7 +3363,7 @@ static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
        rtnh->rtnh_hops = 0;
        rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
 
-       if (rt6_nexthop_info(skb, rt, &flags) < 0)
+       if (rt6_nexthop_info(skb, rt, &flags, true) < 0)
                goto nla_put_failure;
 
        rtnh->rtnh_flags = flags;
@@ -3422,6 +3423,8 @@ static int rt6_fill_node(struct net *net,
        }
        else if (rt->rt6i_flags & RTF_LOCAL)
                rtm->rtm_type = RTN_LOCAL;
+       else if (rt->rt6i_flags & RTF_ANYCAST)
+               rtm->rtm_type = RTN_ANYCAST;
        else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
                rtm->rtm_type = RTN_LOCAL;
        else
@@ -3515,7 +3518,7 @@ static int rt6_fill_node(struct net *net,
 
                nla_nest_end(skb, mp);
        } else {
-               if (rt6_nexthop_info(skb, rt, &rtm->rtm_flags) < 0)
+               if (rt6_nexthop_info(skb, rt, &rtm->rtm_flags, false) < 0)
                        goto nla_put_failure;
        }
 
index 60a5295a7de6e877f5ab80ef32314c573c289d81..49fa2e8c3fa9212eef1198a1077a6726f0f1b6fc 100644 (file)
@@ -391,10 +391,12 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        np = inet6_sk(sk);
 
        if (type == NDISC_REDIRECT) {
-               struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
+               if (!sock_owned_by_user(sk)) {
+                       struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
 
-               if (dst)
-                       dst->ops->redirect(dst, sk, skb);
+                       if (dst)
+                               dst->ops->redirect(dst, sk, skb);
+               }
                goto out;
        }
 
index 4e4c401e3bc69020deaa4af1c10633288faedf13..e28082f0a307eb68ac13987580d8d9f65358212f 100644 (file)
@@ -1035,6 +1035,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        ipc6.hlimit = -1;
        ipc6.tclass = -1;
        ipc6.dontfrag = -1;
+       sockc.tsflags = sk->sk_tsflags;
 
        /* destination address check */
        if (sin6) {
@@ -1159,7 +1160,6 @@ do_udp_sendmsg:
 
        fl6.flowi6_mark = sk->sk_mark;
        fl6.flowi6_uid = sk->sk_uid;
-       sockc.tsflags = sk->sk_tsflags;
 
        if (msg->msg_controllen) {
                opt = &opt_space;
index 81adc29a448dc5be56b96ddd5c42321417371d37..8d77ad5cadaff3aa1feb18f168e779c5a6e7f917 100644 (file)
@@ -828,7 +828,8 @@ out:
  *    Wait for incoming connection
  *
  */
-static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
+static int irda_accept(struct socket *sock, struct socket *newsock, int flags,
+                      bool kern)
 {
        struct sock *sk = sock->sk;
        struct irda_sock *new, *self = irda_sk(sk);
@@ -836,7 +837,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
        struct sk_buff *skb = NULL;
        int err;
 
-       err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0);
+       err = irda_create(sock_net(sk), newsock, sk->sk_protocol, kern);
        if (err)
                return err;
 
index 89bbde1081ce5eb56c0c6a1c7c18b030f3de1198..84de7b6326dcdf7fcf0d8cb73f738d9c21c2f9fe 100644 (file)
@@ -938,7 +938,7 @@ done:
 
 /* Accept a pending connection */
 static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
-                           int flags)
+                           int flags, bool kern)
 {
        DECLARE_WAITQUEUE(wait, current);
        struct sock *sk = sock->sk, *nsk;
index 06186d608a274eb46cd768610c67e8a5a8e84c15..cb4fff785cbf5aaad520442dc243ae62dc5750ea 100644 (file)
@@ -641,11 +641,13 @@ static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb)
  *     @sock: Socket which connections arrive on.
  *     @newsock: Socket to move incoming connection to.
  *     @flags: User specified operational flags.
+ *     @kern: If the socket is kernel internal
  *
  *     Accept a new incoming connection.
  *     Returns 0 upon success, negative otherwise.
  */
-static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags,
+                        bool kern)
 {
        struct sock *sk = sock->sk, *newsk;
        struct llc_sock *llc, *newllc;
index 3818686182b210be11025ff69d82f58e4e08e401..6414079aa7297eee8fbd6320fb4392c6d8865e34 100644 (file)
@@ -1269,6 +1269,8 @@ static void mpls_ifdown(struct net_device *dev, int event)
 {
        struct mpls_route __rcu **platform_label;
        struct net *net = dev_net(dev);
+       unsigned int nh_flags = RTNH_F_DEAD | RTNH_F_LINKDOWN;
+       unsigned int alive;
        unsigned index;
 
        platform_label = rtnl_dereference(net->mpls.platform_label);
@@ -1278,9 +1280,11 @@ static void mpls_ifdown(struct net_device *dev, int event)
                if (!rt)
                        continue;
 
+               alive = 0;
                change_nexthops(rt) {
                        if (rtnl_dereference(nh->nh_dev) != dev)
-                               continue;
+                               goto next;
+
                        switch (event) {
                        case NETDEV_DOWN:
                        case NETDEV_UNREGISTER:
@@ -1288,12 +1292,16 @@ static void mpls_ifdown(struct net_device *dev, int event)
                                /* fall through */
                        case NETDEV_CHANGE:
                                nh->nh_flags |= RTNH_F_LINKDOWN;
-                               ACCESS_ONCE(rt->rt_nhn_alive) = rt->rt_nhn_alive - 1;
                                break;
                        }
                        if (event == NETDEV_UNREGISTER)
                                RCU_INIT_POINTER(nh->nh_dev, NULL);
+next:
+                       if (!(nh->nh_flags & nh_flags))
+                               alive++;
                } endfor_nexthops(rt);
+
+               WRITE_ONCE(rt->rt_nhn_alive, alive);
        }
 }
 
@@ -2028,6 +2036,7 @@ static void mpls_net_exit(struct net *net)
        for (index = 0; index < platform_labels; index++) {
                struct mpls_route *rt = rtnl_dereference(platform_label[index]);
                RCU_INIT_POINTER(platform_label[index], NULL);
+               mpls_notify_route(net, index, rt, NULL, NULL);
                mpls_rt_free(rt);
        }
        rtnl_unlock();
index 071b97fcbefb083ded417e06e739a4622b237fe8..ffb78e5f7b70912a2bba608a7f32f0a2bc486adc 100644 (file)
@@ -181,7 +181,11 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
 unsigned int nf_conntrack_max __read_mostly;
 seqcount_t nf_conntrack_generation __read_mostly;
 
-DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
+/* nf_conn must be 8 bytes aligned, as the 3 LSB bits are used
+ * for the nfctinfo. We cheat by (ab)using the PER CPU cache line
+ * alignment to enforce this.
+ */
+DEFINE_PER_CPU_ALIGNED(struct nf_conn, nf_conntrack_untracked);
 EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked);
 
 static unsigned int nf_conntrack_hash_rnd __read_mostly;
index 31d358691af0963c664c742d180e79c664590005..804e8a0ab36ef56b120ea89be1994b39eca5bc36 100644 (file)
@@ -33,8 +33,16 @@ sctp_manip_pkt(struct sk_buff *skb,
               enum nf_nat_manip_type maniptype)
 {
        sctp_sctphdr_t *hdr;
+       int hdrsize = 8;
 
-       if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
+       /* This could be an inner header returned in imcp packet; in such
+        * cases we cannot update the checksum field since it is outside
+        * of the 8 bytes of transport layer headers we are guaranteed.
+        */
+       if (skb->len >= hdroff + sizeof(*hdr))
+               hdrsize = sizeof(*hdr);
+
+       if (!skb_make_writable(skb, hdroff + hdrsize))
                return false;
 
        hdr = (struct sctphdr *)(skb->data + hdroff);
@@ -47,6 +55,9 @@ sctp_manip_pkt(struct sk_buff *skb,
                hdr->dest = tuple->dst.u.sctp.port;
        }
 
+       if (hdrsize < sizeof(*hdr))
+               return true;
+
        if (skb->ip_summed != CHECKSUM_PARTIAL) {
                hdr->checksum = sctp_compute_cksum(skb, hdroff);
                skb->ip_summed = CHECKSUM_NONE;
index 5e0ccfd5bb37d1cbebb7e03b0998b7c24cca024d..434c739dfecaa8727dc193f8ad86e18133932660 100644 (file)
@@ -3145,7 +3145,6 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                iter.count      = 0;
                iter.err        = 0;
                iter.fn         = nf_tables_bind_check_setelem;
-               iter.flush      = false;
 
                set->ops->walk(ctx, set, &iter);
                if (iter.err < 0)
@@ -3399,7 +3398,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
        args.iter.count         = 0;
        args.iter.err           = 0;
        args.iter.fn            = nf_tables_dump_setelem;
-       args.iter.flush         = false;
        set->ops->walk(&ctx, set, &args.iter);
 
        nla_nest_end(skb, nest);
@@ -3963,7 +3961,6 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
                struct nft_set_iter iter = {
                        .genmask        = genmask,
                        .fn             = nft_flush_set,
-                       .flush          = true,
                };
                set->ops->walk(&ctx, set, &iter);
 
@@ -5114,7 +5111,6 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
                        iter.count      = 0;
                        iter.err        = 0;
                        iter.fn         = nf_tables_loop_check_setelem;
-                       iter.flush      = false;
 
                        set->ops->walk(ctx, set, &iter);
                        if (iter.err < 0)
index bf548a7a71ec9b49cf308af041811d2eb5f33c8c..0264258c46feb5071a8eebcf9299b4b717fd0a32 100644 (file)
@@ -83,7 +83,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
 
        switch (priv->key) {
        case NFT_CT_DIRECTION:
-               *dest = CTINFO2DIR(ctinfo);
+               nft_reg_store8(dest, CTINFO2DIR(ctinfo));
                return;
        case NFT_CT_STATUS:
                *dest = ct->status;
@@ -151,20 +151,22 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
                return;
        }
        case NFT_CT_L3PROTOCOL:
-               *dest = nf_ct_l3num(ct);
+               nft_reg_store8(dest, nf_ct_l3num(ct));
                return;
        case NFT_CT_PROTOCOL:
-               *dest = nf_ct_protonum(ct);
+               nft_reg_store8(dest, nf_ct_protonum(ct));
                return;
 #ifdef CONFIG_NF_CONNTRACK_ZONES
        case NFT_CT_ZONE: {
                const struct nf_conntrack_zone *zone = nf_ct_zone(ct);
+               u16 zoneid;
 
                if (priv->dir < IP_CT_DIR_MAX)
-                       *dest = nf_ct_zone_id(zone, priv->dir);
+                       zoneid = nf_ct_zone_id(zone, priv->dir);
                else
-                       *dest = zone->id;
+                       zoneid = zone->id;
 
+               nft_reg_store16(dest, zoneid);
                return;
        }
 #endif
@@ -183,10 +185,10 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
                       nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
                return;
        case NFT_CT_PROTO_SRC:
-               *dest = (__force __u16)tuple->src.u.all;
+               nft_reg_store16(dest, (__force u16)tuple->src.u.all);
                return;
        case NFT_CT_PROTO_DST:
-               *dest = (__force __u16)tuple->dst.u.all;
+               nft_reg_store16(dest, (__force u16)tuple->dst.u.all);
                return;
        default:
                break;
@@ -205,7 +207,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
        const struct nft_ct *priv = nft_expr_priv(expr);
        struct sk_buff *skb = pkt->skb;
        enum ip_conntrack_info ctinfo;
-       u16 value = regs->data[priv->sreg];
+       u16 value = nft_reg_load16(&regs->data[priv->sreg]);
        struct nf_conn *ct;
 
        ct = nf_ct_get(skb, &ctinfo);
@@ -542,7 +544,8 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
                case IP_CT_DIR_REPLY:
                        break;
                default:
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto err1;
                }
        }
 
index e1f5ca9b423b5ffda43ec5519d4c8832ce695899..7b60e01f38ff9f2f9fa7d28f6f99b4f889d190d7 100644 (file)
@@ -45,16 +45,15 @@ void nft_meta_get_eval(const struct nft_expr *expr,
                *dest = skb->len;
                break;
        case NFT_META_PROTOCOL:
-               *dest = 0;
-               *(__be16 *)dest = skb->protocol;
+               nft_reg_store16(dest, (__force u16)skb->protocol);
                break;
        case NFT_META_NFPROTO:
-               *dest = nft_pf(pkt);
+               nft_reg_store8(dest, nft_pf(pkt));
                break;
        case NFT_META_L4PROTO:
                if (!pkt->tprot_set)
                        goto err;
-               *dest = pkt->tprot;
+               nft_reg_store8(dest, pkt->tprot);
                break;
        case NFT_META_PRIORITY:
                *dest = skb->priority;
@@ -85,14 +84,12 @@ void nft_meta_get_eval(const struct nft_expr *expr,
        case NFT_META_IIFTYPE:
                if (in == NULL)
                        goto err;
-               *dest = 0;
-               *(u16 *)dest = in->type;
+               nft_reg_store16(dest, in->type);
                break;
        case NFT_META_OIFTYPE:
                if (out == NULL)
                        goto err;
-               *dest = 0;
-               *(u16 *)dest = out->type;
+               nft_reg_store16(dest, out->type);
                break;
        case NFT_META_SKUID:
                sk = skb_to_full_sk(skb);
@@ -142,19 +139,19 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 #endif
        case NFT_META_PKTTYPE:
                if (skb->pkt_type != PACKET_LOOPBACK) {
-                       *dest = skb->pkt_type;
+                       nft_reg_store8(dest, skb->pkt_type);
                        break;
                }
 
                switch (nft_pf(pkt)) {
                case NFPROTO_IPV4:
                        if (ipv4_is_multicast(ip_hdr(skb)->daddr))
-                               *dest = PACKET_MULTICAST;
+                               nft_reg_store8(dest, PACKET_MULTICAST);
                        else
-                               *dest = PACKET_BROADCAST;
+                               nft_reg_store8(dest, PACKET_BROADCAST);
                        break;
                case NFPROTO_IPV6:
-                       *dest = PACKET_MULTICAST;
+                       nft_reg_store8(dest, PACKET_MULTICAST);
                        break;
                case NFPROTO_NETDEV:
                        switch (skb->protocol) {
@@ -168,14 +165,14 @@ void nft_meta_get_eval(const struct nft_expr *expr,
                                        goto err;
 
                                if (ipv4_is_multicast(iph->daddr))
-                                       *dest = PACKET_MULTICAST;
+                                       nft_reg_store8(dest, PACKET_MULTICAST);
                                else
-                                       *dest = PACKET_BROADCAST;
+                                       nft_reg_store8(dest, PACKET_BROADCAST);
 
                                break;
                        }
                        case htons(ETH_P_IPV6):
-                               *dest = PACKET_MULTICAST;
+                               nft_reg_store8(dest, PACKET_MULTICAST);
                                break;
                        default:
                                WARN_ON_ONCE(1);
@@ -230,7 +227,9 @@ void nft_meta_set_eval(const struct nft_expr *expr,
 {
        const struct nft_meta *meta = nft_expr_priv(expr);
        struct sk_buff *skb = pkt->skb;
-       u32 value = regs->data[meta->sreg];
+       u32 *sreg = &regs->data[meta->sreg];
+       u32 value = *sreg;
+       u8 pkt_type;
 
        switch (meta->key) {
        case NFT_META_MARK:
@@ -240,9 +239,12 @@ void nft_meta_set_eval(const struct nft_expr *expr,
                skb->priority = value;
                break;
        case NFT_META_PKTTYPE:
-               if (skb->pkt_type != value &&
-                   skb_pkt_type_ok(value) && skb_pkt_type_ok(skb->pkt_type))
-                       skb->pkt_type = value;
+               pkt_type = nft_reg_load8(sreg);
+
+               if (skb->pkt_type != pkt_type &&
+                   skb_pkt_type_ok(pkt_type) &&
+                   skb_pkt_type_ok(skb->pkt_type))
+                       skb->pkt_type = pkt_type;
                break;
        case NFT_META_NFTRACE:
                skb->nf_trace = !!value;
index 19a7bf3236f968725a29e827012af301781802df..439e0bd152a004c98664a19ae6c920458fa6160a 100644 (file)
@@ -65,10 +65,10 @@ static void nft_nat_eval(const struct nft_expr *expr,
        }
 
        if (priv->sreg_proto_min) {
-               range.min_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_min];
-               range.max_proto.all =
-                       *(__be16 *)&regs->data[priv->sreg_proto_max];
+               range.min_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_min]);
+               range.max_proto.all = (__force __be16)nft_reg_load16(
+                       &regs->data[priv->sreg_proto_max]);
                range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
        }
 
index 152d226552c174929fd8973f023eaac888e4b0a9..8ebbc2940f4c593d393c65bd5674d90feb585d98 100644 (file)
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
 
+struct nft_bitmap_elem {
+       struct list_head        head;
+       struct nft_set_ext      ext;
+};
+
 /* This bitmap uses two bits to represent one element. These two bits determine
  * the element state in the current and the future generation.
  *
  *      restore its previous state.
  */
 struct nft_bitmap {
-       u16     bitmap_size;
-       u8      bitmap[];
+       struct  list_head       list;
+       u16                     bitmap_size;
+       u8                      bitmap[];
 };
 
-static inline void nft_bitmap_location(u32 key, u32 *idx, u32 *off)
+static inline void nft_bitmap_location(const struct nft_set *set,
+                                      const void *key,
+                                      u32 *idx, u32 *off)
 {
-       u32 k = (key << 1);
+       u32 k;
+
+       if (set->klen == 2)
+               k = *(u16 *)key;
+       else
+               k = *(u8 *)key;
+       k <<= 1;
 
        *idx = k / BITS_PER_BYTE;
        *off = k % BITS_PER_BYTE;
@@ -69,26 +83,48 @@ static bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
        u8 genmask = nft_genmask_cur(net);
        u32 idx, off;
 
-       nft_bitmap_location(*key, &idx, &off);
+       nft_bitmap_location(set, key, &idx, &off);
 
        return nft_bitmap_active(priv->bitmap, idx, off, genmask);
 }
 
+static struct nft_bitmap_elem *
+nft_bitmap_elem_find(const struct nft_set *set, struct nft_bitmap_elem *this,
+                    u8 genmask)
+{
+       const struct nft_bitmap *priv = nft_set_priv(set);
+       struct nft_bitmap_elem *be;
+
+       list_for_each_entry_rcu(be, &priv->list, head) {
+               if (memcmp(nft_set_ext_key(&be->ext),
+                          nft_set_ext_key(&this->ext), set->klen) ||
+                   !nft_set_elem_active(&be->ext, genmask))
+                       continue;
+
+               return be;
+       }
+       return NULL;
+}
+
 static int nft_bitmap_insert(const struct net *net, const struct nft_set *set,
                             const struct nft_set_elem *elem,
-                            struct nft_set_ext **_ext)
+                            struct nft_set_ext **ext)
 {
        struct nft_bitmap *priv = nft_set_priv(set);
-       struct nft_set_ext *ext = elem->priv;
+       struct nft_bitmap_elem *new = elem->priv, *be;
        u8 genmask = nft_genmask_next(net);
        u32 idx, off;
 
-       nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
-       if (nft_bitmap_active(priv->bitmap, idx, off, genmask))
+       be = nft_bitmap_elem_find(set, new, genmask);
+       if (be) {
+               *ext = &be->ext;
                return -EEXIST;
+       }
 
+       nft_bitmap_location(set, nft_set_ext_key(&new->ext), &idx, &off);
        /* Enter 01 state. */
        priv->bitmap[idx] |= (genmask << off);
+       list_add_tail_rcu(&new->head, &priv->list);
 
        return 0;
 }
@@ -98,13 +134,14 @@ static void nft_bitmap_remove(const struct net *net,
                              const struct nft_set_elem *elem)
 {
        struct nft_bitmap *priv = nft_set_priv(set);
-       struct nft_set_ext *ext = elem->priv;
+       struct nft_bitmap_elem *be = elem->priv;
        u8 genmask = nft_genmask_next(net);
        u32 idx, off;
 
-       nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+       nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
        /* Enter 00 state. */
        priv->bitmap[idx] &= ~(genmask << off);
+       list_del_rcu(&be->head);
 }
 
 static void nft_bitmap_activate(const struct net *net,
@@ -112,74 +149,52 @@ static void nft_bitmap_activate(const struct net *net,
                                const struct nft_set_elem *elem)
 {
        struct nft_bitmap *priv = nft_set_priv(set);
-       struct nft_set_ext *ext = elem->priv;
+       struct nft_bitmap_elem *be = elem->priv;
        u8 genmask = nft_genmask_next(net);
        u32 idx, off;
 
-       nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+       nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
        /* Enter 11 state. */
        priv->bitmap[idx] |= (genmask << off);
+       nft_set_elem_change_active(net, set, &be->ext);
 }
 
 static bool nft_bitmap_flush(const struct net *net,
-                            const struct nft_set *set, void *ext)
+                            const struct nft_set *set, void *_be)
 {
        struct nft_bitmap *priv = nft_set_priv(set);
        u8 genmask = nft_genmask_next(net);
+       struct nft_bitmap_elem *be = _be;
        u32 idx, off;
 
-       nft_bitmap_location(nft_set_ext_key(ext)->data[0], &idx, &off);
+       nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
        /* Enter 10 state, similar to deactivation. */
        priv->bitmap[idx] &= ~(genmask << off);
+       nft_set_elem_change_active(net, set, &be->ext);
 
        return true;
 }
 
-static struct nft_set_ext *nft_bitmap_ext_alloc(const struct nft_set *set,
-                                               const struct nft_set_elem *elem)
-{
-       struct nft_set_ext_tmpl tmpl;
-       struct nft_set_ext *ext;
-
-       nft_set_ext_prepare(&tmpl);
-       nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
-
-       ext = kzalloc(tmpl.len, GFP_KERNEL);
-       if (!ext)
-               return NULL;
-
-       nft_set_ext_init(ext, &tmpl);
-       memcpy(nft_set_ext_key(ext), elem->key.val.data, set->klen);
-
-       return ext;
-}
-
 static void *nft_bitmap_deactivate(const struct net *net,
                                   const struct nft_set *set,
                                   const struct nft_set_elem *elem)
 {
        struct nft_bitmap *priv = nft_set_priv(set);
+       struct nft_bitmap_elem *this = elem->priv, *be;
        u8 genmask = nft_genmask_next(net);
-       struct nft_set_ext *ext;
-       u32 idx, off, key = 0;
-
-       memcpy(&key, elem->key.val.data, set->klen);
-       nft_bitmap_location(key, &idx, &off);
+       u32 idx, off;
 
-       if (!nft_bitmap_active(priv->bitmap, idx, off, genmask))
-               return NULL;
+       nft_bitmap_location(set, elem->key.val.data, &idx, &off);
 
-       /* We have no real set extension since this is a bitmap, allocate this
-        * dummy object that is released from the commit/abort path.
-        */
-       ext = nft_bitmap_ext_alloc(set, elem);
-       if (!ext)
+       be = nft_bitmap_elem_find(set, this, genmask);
+       if (!be)
                return NULL;
 
        /* Enter 10 state. */
        priv->bitmap[idx] &= ~(genmask << off);
+       nft_set_elem_change_active(net, set, &be->ext);
 
-       return ext;
+       return be;
 }
 
 static void nft_bitmap_walk(const struct nft_ctx *ctx,
@@ -187,47 +202,23 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
                            struct nft_set_iter *iter)
 {
        const struct nft_bitmap *priv = nft_set_priv(set);
-       struct nft_set_ext_tmpl tmpl;
+       struct nft_bitmap_elem *be;
        struct nft_set_elem elem;
-       struct nft_set_ext *ext;
-       int idx, off;
-       u16 key;
-
-       nft_set_ext_prepare(&tmpl);
-       nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
-
-       for (idx = 0; idx < priv->bitmap_size; idx++) {
-               for (off = 0; off < BITS_PER_BYTE; off += 2) {
-                       if (iter->count < iter->skip)
-                               goto cont;
-
-                       if (!nft_bitmap_active(priv->bitmap, idx, off,
-                                              iter->genmask))
-                               goto cont;
-
-                       ext = kzalloc(tmpl.len, GFP_KERNEL);
-                       if (!ext) {
-                               iter->err = -ENOMEM;
-                               return;
-                       }
-                       nft_set_ext_init(ext, &tmpl);
-                       key = ((idx * BITS_PER_BYTE) + off) >> 1;
-                       memcpy(nft_set_ext_key(ext), &key, set->klen);
-
-                       elem.priv = ext;
-                       iter->err = iter->fn(ctx, set, iter, &elem);
-
-                       /* On set flush, this dummy extension object is released
-                        * from the commit/abort path.
-                        */
-                       if (!iter->flush)
-                               kfree(ext);
-
-                       if (iter->err < 0)
-                               return;
+
+       list_for_each_entry_rcu(be, &priv->list, head) {
+               if (iter->count < iter->skip)
+                       goto cont;
+               if (!nft_set_elem_active(&be->ext, iter->genmask))
+                       goto cont;
+
+               elem.priv = be;
+
+               iter->err = iter->fn(ctx, set, iter, &elem);
+
+               if (iter->err < 0)
+                       return;
 cont:
-                       iter->count++;
-               }
+               iter->count++;
        }
 }
 
@@ -258,6 +249,7 @@ static int nft_bitmap_init(const struct nft_set *set,
 {
        struct nft_bitmap *priv = nft_set_priv(set);
 
+       INIT_LIST_HEAD(&priv->list);
        priv->bitmap_size = nft_bitmap_size(set->klen);
 
        return 0;
@@ -283,6 +275,7 @@ static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,
 
 static struct nft_set_ops nft_bitmap_ops __read_mostly = {
        .privsize       = nft_bitmap_privsize,
+       .elemsize       = offsetof(struct nft_bitmap_elem, ext),
        .estimate       = nft_bitmap_estimate,
        .init           = nft_bitmap_init,
        .destroy        = nft_bitmap_destroy,
index 7b73c7c161a9680b8691a712c31073b7789620f7..596eaff66649e5955d6c0f349f062b6d8360dc2d 100644 (file)
@@ -96,6 +96,44 @@ EXPORT_SYMBOL_GPL(nl_table);
 
 static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
 
+static struct lock_class_key nlk_cb_mutex_keys[MAX_LINKS];
+
+static const char *const nlk_cb_mutex_key_strings[MAX_LINKS + 1] = {
+       "nlk_cb_mutex-ROUTE",
+       "nlk_cb_mutex-1",
+       "nlk_cb_mutex-USERSOCK",
+       "nlk_cb_mutex-FIREWALL",
+       "nlk_cb_mutex-SOCK_DIAG",
+       "nlk_cb_mutex-NFLOG",
+       "nlk_cb_mutex-XFRM",
+       "nlk_cb_mutex-SELINUX",
+       "nlk_cb_mutex-ISCSI",
+       "nlk_cb_mutex-AUDIT",
+       "nlk_cb_mutex-FIB_LOOKUP",
+       "nlk_cb_mutex-CONNECTOR",
+       "nlk_cb_mutex-NETFILTER",
+       "nlk_cb_mutex-IP6_FW",
+       "nlk_cb_mutex-DNRTMSG",
+       "nlk_cb_mutex-KOBJECT_UEVENT",
+       "nlk_cb_mutex-GENERIC",
+       "nlk_cb_mutex-17",
+       "nlk_cb_mutex-SCSITRANSPORT",
+       "nlk_cb_mutex-ECRYPTFS",
+       "nlk_cb_mutex-RDMA",
+       "nlk_cb_mutex-CRYPTO",
+       "nlk_cb_mutex-SMC",
+       "nlk_cb_mutex-23",
+       "nlk_cb_mutex-24",
+       "nlk_cb_mutex-25",
+       "nlk_cb_mutex-26",
+       "nlk_cb_mutex-27",
+       "nlk_cb_mutex-28",
+       "nlk_cb_mutex-29",
+       "nlk_cb_mutex-30",
+       "nlk_cb_mutex-31",
+       "nlk_cb_mutex-MAX_LINKS"
+};
+
 static int netlink_dump(struct sock *sk);
 static void netlink_skb_destructor(struct sk_buff *skb);
 
@@ -585,6 +623,9 @@ static int __netlink_create(struct net *net, struct socket *sock,
        } else {
                nlk->cb_mutex = &nlk->cb_def_mutex;
                mutex_init(nlk->cb_mutex);
+               lockdep_set_class_and_name(nlk->cb_mutex,
+                                          nlk_cb_mutex_keys + protocol,
+                                          nlk_cb_mutex_key_strings[protocol]);
        }
        init_waitqueue_head(&nlk->wait);
 
index fb6e10fdb2174320c96608aea63d3c484d3625a0..92e0981f74040d7029b65863167b459322612024 100644 (file)
@@ -783,8 +783,10 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
 
                if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
                                   cb->nlh->nlmsg_seq, NLM_F_MULTI,
-                                  skb, CTRL_CMD_NEWFAMILY) < 0)
+                                  skb, CTRL_CMD_NEWFAMILY) < 0) {
+                       n--;
                        break;
+               }
        }
 
        cb->args[0] = n;
index 4bbf4526b88566d7c3f14e602f279b7e2570113c..ebf16f7f90892dd3029e643835859459baec4507 100644 (file)
@@ -765,7 +765,8 @@ out_release:
        return err;
 }
 
-static int nr_accept(struct socket *sock, struct socket *newsock, int flags)
+static int nr_accept(struct socket *sock, struct socket *newsock, int flags,
+                    bool kern)
 {
        struct sk_buff *skb;
        struct sock *newsk;
index 879885b31cce5ff2461c3a1524612527b9383bbd..2ffb18e73df6c03072fffeb68b660fb2f884eb45 100644 (file)
@@ -441,7 +441,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
 }
 
 static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
-                           int flags)
+                           int flags, bool kern)
 {
        DECLARE_WAITQUEUE(wait, current);
        struct sock *sk = sock->sk, *new_sk;
index 6f5fa50f716d066333b30edde43e5165b9fe94be..1105a838bab83f9fe647423060d08e4a415bab61 100644 (file)
@@ -604,7 +604,7 @@ static int ip_tun_from_nlattr(const struct nlattr *attr,
                        ipv4 = true;
                        break;
                case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
-                       SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
+                       SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src,
                                        nla_get_in6_addr(a), is_mask);
                        ipv6 = true;
                        break;
@@ -665,6 +665,8 @@ static int ip_tun_from_nlattr(const struct nlattr *attr,
                        tun_flags |= TUNNEL_VXLAN_OPT;
                        opts_type = type;
                        break;
+               case OVS_TUNNEL_KEY_ATTR_PAD:
+                       break;
                default:
                        OVS_NLERR(log, "Unknown IP tunnel attribute %d",
                                  type);
index 222bedcd95754c80644748daba365dc00b10fd8c..e81537991ddf0d67e6eca19fc9eb6f442d3c06a4 100644 (file)
@@ -772,7 +772,8 @@ static void pep_sock_close(struct sock *sk, long timeout)
        sock_put(sk);
 }
 
-static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)
+static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
+                                   bool kern)
 {
        struct pep_sock *pn = pep_sk(sk), *newpn;
        struct sock *newsk = NULL;
@@ -846,7 +847,8 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)
        }
 
        /* Create a new to-be-accepted sock */
-       newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_KERNEL, sk->sk_prot, 0);
+       newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_KERNEL, sk->sk_prot,
+                        kern);
        if (!newsk) {
                pep_reject_conn(sk, skb, PN_PIPE_ERR_OVERLOAD, GFP_KERNEL);
                err = -ENOBUFS;
index a6c8da3ee89349989a9f23e095b98293050da73a..64634e3ec2fc78ebb84ad8873f6e446d06844493 100644 (file)
@@ -305,7 +305,7 @@ out:
 }
 
 static int pn_socket_accept(struct socket *sock, struct socket *newsock,
-                               int flags)
+                           int flags, bool kern)
 {
        struct sock *sk = sock->sk;
        struct sock *newsk;
@@ -314,7 +314,7 @@ static int pn_socket_accept(struct socket *sock, struct socket *newsock,
        if (unlikely(sk->sk_state != TCP_LISTEN))
                return -EINVAL;
 
-       newsk = sk->sk_prot->accept(sk, flags, &err);
+       newsk = sk->sk_prot->accept(sk, flags, &err, kern);
        if (!newsk)
                return err;
 
index 0e04dcceb1d416438be8bb40fc68253f336f631d..1fa75ab7b733230585666abcb7279ba691365256 100644 (file)
@@ -429,6 +429,7 @@ void rds_conn_destroy(struct rds_connection *conn)
         */
        rds_cong_remove_conn(conn);
 
+       put_net(conn->c_net);
        kmem_cache_free(rds_conn_slab, conn);
 
        spin_lock_irqsave(&rds_conn_lock, flags);
index ce3775abc6e7a1d30e335aaea749a9840e949786..1c38d2c7caa8e955585b45f0c9218a0775013b4d 100644 (file)
@@ -442,7 +442,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
                ic->i_send_cq = NULL;
                ibdev_put_vector(rds_ibdev, ic->i_scq_vector);
                rdsdebug("ib_create_cq send failed: %d\n", ret);
-               goto out;
+               goto rds_ibdev_out;
        }
 
        ic->i_rcq_vector = ibdev_get_unused_vector(rds_ibdev);
@@ -456,19 +456,19 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
                ic->i_recv_cq = NULL;
                ibdev_put_vector(rds_ibdev, ic->i_rcq_vector);
                rdsdebug("ib_create_cq recv failed: %d\n", ret);
-               goto out;
+               goto send_cq_out;
        }
 
        ret = ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP);
        if (ret) {
                rdsdebug("ib_req_notify_cq send failed: %d\n", ret);
-               goto out;
+               goto recv_cq_out;
        }
 
        ret = ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED);
        if (ret) {
                rdsdebug("ib_req_notify_cq recv failed: %d\n", ret);
-               goto out;
+               goto recv_cq_out;
        }
 
        /* XXX negotiate max send/recv with remote? */
@@ -494,7 +494,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        ret = rdma_create_qp(ic->i_cm_id, ic->i_pd, &attr);
        if (ret) {
                rdsdebug("rdma_create_qp failed: %d\n", ret);
-               goto out;
+               goto recv_cq_out;
        }
 
        ic->i_send_hdrs = ib_dma_alloc_coherent(dev,
@@ -504,7 +504,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        if (!ic->i_send_hdrs) {
                ret = -ENOMEM;
                rdsdebug("ib_dma_alloc_coherent send failed\n");
-               goto out;
+               goto qp_out;
        }
 
        ic->i_recv_hdrs = ib_dma_alloc_coherent(dev,
@@ -514,7 +514,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        if (!ic->i_recv_hdrs) {
                ret = -ENOMEM;
                rdsdebug("ib_dma_alloc_coherent recv failed\n");
-               goto out;
+               goto send_hdrs_dma_out;
        }
 
        ic->i_ack = ib_dma_alloc_coherent(dev, sizeof(struct rds_header),
@@ -522,7 +522,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        if (!ic->i_ack) {
                ret = -ENOMEM;
                rdsdebug("ib_dma_alloc_coherent ack failed\n");
-               goto out;
+               goto recv_hdrs_dma_out;
        }
 
        ic->i_sends = vzalloc_node(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work),
@@ -530,7 +530,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        if (!ic->i_sends) {
                ret = -ENOMEM;
                rdsdebug("send allocation failed\n");
-               goto out;
+               goto ack_dma_out;
        }
 
        ic->i_recvs = vzalloc_node(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work),
@@ -538,7 +538,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        if (!ic->i_recvs) {
                ret = -ENOMEM;
                rdsdebug("recv allocation failed\n");
-               goto out;
+               goto sends_out;
        }
 
        rds_ib_recv_init_ack(ic);
@@ -546,8 +546,33 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
        rdsdebug("conn %p pd %p cq %p %p\n", conn, ic->i_pd,
                 ic->i_send_cq, ic->i_recv_cq);
 
-out:
+       return ret;
+
+sends_out:
+       vfree(ic->i_sends);
+ack_dma_out:
+       ib_dma_free_coherent(dev, sizeof(struct rds_header),
+                            ic->i_ack, ic->i_ack_dma);
+recv_hdrs_dma_out:
+       ib_dma_free_coherent(dev, ic->i_recv_ring.w_nr *
+                                       sizeof(struct rds_header),
+                                       ic->i_recv_hdrs, ic->i_recv_hdrs_dma);
+send_hdrs_dma_out:
+       ib_dma_free_coherent(dev, ic->i_send_ring.w_nr *
+                                       sizeof(struct rds_header),
+                                       ic->i_send_hdrs, ic->i_send_hdrs_dma);
+qp_out:
+       rdma_destroy_qp(ic->i_cm_id);
+recv_cq_out:
+       if (!ib_destroy_cq(ic->i_recv_cq))
+               ic->i_recv_cq = NULL;
+send_cq_out:
+       if (!ib_destroy_cq(ic->i_send_cq))
+               ic->i_send_cq = NULL;
+rds_ibdev_out:
+       rds_ib_remove_conn(rds_ibdev, conn);
        rds_ib_dev_put(rds_ibdev);
+
        return ret;
 }
 
index 39518ef7af4dfbada74af4a685cd8fe8dbaf9e40..82d38ccf5e8bcf99eefd20934744cbeb7410406b 100644 (file)
@@ -147,7 +147,7 @@ struct rds_connection {
 
        /* Protocol version */
        unsigned int            c_version;
-       possible_net_t          c_net;
+       struct net              *c_net;
 
        struct list_head        c_map_item;
        unsigned long           c_map_queued;
@@ -162,13 +162,13 @@ struct rds_connection {
 static inline
 struct net *rds_conn_net(struct rds_connection *conn)
 {
-       return read_pnet(&conn->c_net);
+       return conn->c_net;
 }
 
 static inline
 void rds_conn_net_set(struct rds_connection *conn, struct net *net)
 {
-       write_pnet(&conn->c_net, net);
+       conn->c_net = get_net(net);
 }
 
 #define RDS_FLAG_CONG_BITMAP   0x01
index a973d3b4dff0b2216bf3698cfbfeeb4b227dfc37..22569007677357ba40347ee46e6584c683de2597 100644 (file)
@@ -484,9 +484,10 @@ static void __net_exit rds_tcp_exit_net(struct net *net)
         * we do need to clean up the listen socket here.
         */
        if (rtn->rds_tcp_listen_sock) {
-               rds_tcp_listen_stop(rtn->rds_tcp_listen_sock);
+               struct socket *lsock = rtn->rds_tcp_listen_sock;
+
                rtn->rds_tcp_listen_sock = NULL;
-               flush_work(&rtn->rds_tcp_accept_w);
+               rds_tcp_listen_stop(lsock, &rtn->rds_tcp_accept_w);
        }
 }
 
@@ -523,13 +524,13 @@ static void rds_tcp_kill_sock(struct net *net)
        struct rds_tcp_connection *tc, *_tc;
        LIST_HEAD(tmp_list);
        struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+       struct socket *lsock = rtn->rds_tcp_listen_sock;
 
-       rds_tcp_listen_stop(rtn->rds_tcp_listen_sock);
        rtn->rds_tcp_listen_sock = NULL;
-       flush_work(&rtn->rds_tcp_accept_w);
+       rds_tcp_listen_stop(lsock, &rtn->rds_tcp_accept_w);
        spin_lock_irq(&rds_tcp_conn_lock);
        list_for_each_entry_safe(tc, _tc, &rds_tcp_conn_list, t_tcp_node) {
-               struct net *c_net = read_pnet(&tc->t_cpath->cp_conn->c_net);
+               struct net *c_net = tc->t_cpath->cp_conn->c_net;
 
                if (net != c_net || !tc->t_sock)
                        continue;
@@ -546,8 +547,12 @@ static void rds_tcp_kill_sock(struct net *net)
 void *rds_tcp_listen_sock_def_readable(struct net *net)
 {
        struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+       struct socket *lsock = rtn->rds_tcp_listen_sock;
+
+       if (!lsock)
+               return NULL;
 
-       return rtn->rds_tcp_listen_sock->sk->sk_user_data;
+       return lsock->sk->sk_user_data;
 }
 
 static int rds_tcp_dev_event(struct notifier_block *this,
@@ -584,7 +589,7 @@ static void rds_tcp_sysctl_reset(struct net *net)
 
        spin_lock_irq(&rds_tcp_conn_lock);
        list_for_each_entry_safe(tc, _tc, &rds_tcp_conn_list, t_tcp_node) {
-               struct net *c_net = read_pnet(&tc->t_cpath->cp_conn->c_net);
+               struct net *c_net = tc->t_cpath->cp_conn->c_net;
 
                if (net != c_net || !tc->t_sock)
                        continue;
@@ -638,19 +643,19 @@ static int rds_tcp_init(void)
                goto out;
        }
 
-       ret = register_netdevice_notifier(&rds_tcp_dev_notifier);
-       if (ret) {
-               pr_warn("could not register rds_tcp_dev_notifier\n");
+       ret = rds_tcp_recv_init();
+       if (ret)
                goto out_slab;
-       }
 
        ret = register_pernet_subsys(&rds_tcp_net_ops);
        if (ret)
-               goto out_notifier;
+               goto out_recv;
 
-       ret = rds_tcp_recv_init();
-       if (ret)
+       ret = register_netdevice_notifier(&rds_tcp_dev_notifier);
+       if (ret) {
+               pr_warn("could not register rds_tcp_dev_notifier\n");
                goto out_pernet;
+       }
 
        rds_trans_register(&rds_tcp_transport);
 
@@ -660,9 +665,8 @@ static int rds_tcp_init(void)
 
 out_pernet:
        unregister_pernet_subsys(&rds_tcp_net_ops);
-out_notifier:
-       if (unregister_netdevice_notifier(&rds_tcp_dev_notifier))
-               pr_warn("could not unregister rds_tcp_dev_notifier\n");
+out_recv:
+       rds_tcp_recv_exit();
 out_slab:
        kmem_cache_destroy(rds_tcp_conn_slab);
 out:
index 9a1cc890657679798cf58888c42d5bb2372f0fef..56ea6620fcf97ce40d0926089b5e5b188ea1a1fe 100644 (file)
@@ -66,7 +66,7 @@ void rds_tcp_state_change(struct sock *sk);
 
 /* tcp_listen.c */
 struct socket *rds_tcp_listen_init(struct net *);
-void rds_tcp_listen_stop(struct socket *);
+void rds_tcp_listen_stop(struct socket *sock, struct work_struct *acceptor);
 void rds_tcp_listen_data_ready(struct sock *sk);
 int rds_tcp_accept_one(struct socket *sock);
 int rds_tcp_keepalive(struct socket *sock);
index 67d0929c7d3d0c97ed209af9a67b4d83343c3de1..507678853e6cb3bb769711d22d75f5099228faab 100644 (file)
@@ -133,7 +133,7 @@ int rds_tcp_accept_one(struct socket *sock)
 
        new_sock->type = sock->type;
        new_sock->ops = sock->ops;
-       ret = sock->ops->accept(sock, new_sock, O_NONBLOCK);
+       ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, true);
        if (ret < 0)
                goto out;
 
@@ -223,6 +223,9 @@ void rds_tcp_listen_data_ready(struct sock *sk)
         * before it has been accepted and the accepter has set up their
         * data_ready.. we only want to queue listen work for our listening
         * socket
+        *
+        * (*ready)() may be null if we are racing with netns delete, and
+        * the listen socket is being torn down.
         */
        if (sk->sk_state == TCP_LISTEN)
                rds_tcp_accept_work(sk);
@@ -231,7 +234,8 @@ void rds_tcp_listen_data_ready(struct sock *sk)
 
 out:
        read_unlock_bh(&sk->sk_callback_lock);
-       ready(sk);
+       if (ready)
+               ready(sk);
 }
 
 struct socket *rds_tcp_listen_init(struct net *net)
@@ -271,7 +275,7 @@ out:
        return NULL;
 }
 
-void rds_tcp_listen_stop(struct socket *sock)
+void rds_tcp_listen_stop(struct socket *sock, struct work_struct *acceptor)
 {
        struct sock *sk;
 
@@ -292,5 +296,6 @@ void rds_tcp_listen_stop(struct socket *sock)
 
        /* wait for accepts to stop and close the socket */
        flush_workqueue(rds_wq);
+       flush_work(acceptor);
        sock_release(sock);
 }
index b8a1df2c97853246b2485d9d30caa0e19b61278a..4a9729257023676565a0ff8c140ef56823b6d374 100644 (file)
@@ -871,7 +871,8 @@ out_release:
        return err;
 }
 
-static int rose_accept(struct socket *sock, struct socket *newsock, int flags)
+static int rose_accept(struct socket *sock, struct socket *newsock, int flags,
+                      bool kern)
 {
        struct sk_buff *skb;
        struct sock *newsk;
index 3f9d8d7ec6323a95de3e08d01098abdfcf33ff4f..b099b64366f356c27dea0a4dd215cc1034e61b55 100644 (file)
@@ -275,6 +275,10 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
                rxrpc_conn_retransmit_call(conn, skb);
                return 0;
 
+       case RXRPC_PACKET_TYPE_BUSY:
+               /* Just ignore BUSY packets for now. */
+               return 0;
+
        case RXRPC_PACKET_TYPE_ABORT:
                if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
                                  &wtmp, sizeof(wtmp)) < 0)
index 9f4cfa25af7c92c406e81d8003b8aa07c7892a04..18b2ad8be8e2b57dd57ef846287add68b027b08e 100644 (file)
@@ -420,6 +420,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
                             u16 skew)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       enum rxrpc_call_state state;
        unsigned int offset = sizeof(struct rxrpc_wire_header);
        unsigned int ix;
        rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
@@ -434,14 +435,15 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
        _proto("Rx DATA %%%u { #%u f=%02x }",
               sp->hdr.serial, seq, sp->hdr.flags);
 
-       if (call->state >= RXRPC_CALL_COMPLETE)
+       state = READ_ONCE(call->state);
+       if (state >= RXRPC_CALL_COMPLETE)
                return;
 
        /* Received data implicitly ACKs all of the request packets we sent
         * when we're acting as a client.
         */
-       if ((call->state == RXRPC_CALL_CLIENT_SEND_REQUEST ||
-            call->state == RXRPC_CALL_CLIENT_AWAIT_REPLY) &&
+       if ((state == RXRPC_CALL_CLIENT_SEND_REQUEST ||
+            state == RXRPC_CALL_CLIENT_AWAIT_REPLY) &&
            !rxrpc_receiving_reply(call))
                return;
 
@@ -650,6 +652,7 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        struct rxrpc_peer *peer;
        unsigned int mtu;
+       bool wake = false;
        u32 rwind = ntohl(ackinfo->rwind);
 
        _proto("Rx ACK %%%u Info { rx=%u max=%u rwin=%u jm=%u }",
@@ -657,9 +660,14 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
               ntohl(ackinfo->rxMTU), ntohl(ackinfo->maxMTU),
               rwind, ntohl(ackinfo->jumbo_max));
 
-       if (rwind > RXRPC_RXTX_BUFF_SIZE - 1)
-               rwind = RXRPC_RXTX_BUFF_SIZE - 1;
-       call->tx_winsize = rwind;
+       if (call->tx_winsize != rwind) {
+               if (rwind > RXRPC_RXTX_BUFF_SIZE - 1)
+                       rwind = RXRPC_RXTX_BUFF_SIZE - 1;
+               if (rwind > call->tx_winsize)
+                       wake = true;
+               call->tx_winsize = rwind;
+       }
+
        if (call->cong_ssthresh > rwind)
                call->cong_ssthresh = rwind;
 
@@ -673,6 +681,9 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
                spin_unlock_bh(&peer->lock);
                _net("Net MTU %u (maxdata %u)", peer->mtu, peer->maxdata);
        }
+
+       if (wake)
+               wake_up(&call->waitq);
 }
 
 /*
@@ -799,7 +810,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
                return rxrpc_proto_abort("AK0", call, 0);
 
        /* Ignore ACKs unless we are or have just been transmitting. */
-       switch (call->state) {
+       switch (READ_ONCE(call->state)) {
        case RXRPC_CALL_CLIENT_SEND_REQUEST:
        case RXRPC_CALL_CLIENT_AWAIT_REPLY:
        case RXRPC_CALL_SERVER_SEND_REPLY:
@@ -940,7 +951,7 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 static void rxrpc_input_implicit_end_call(struct rxrpc_connection *conn,
                                          struct rxrpc_call *call)
 {
-       switch (call->state) {
+       switch (READ_ONCE(call->state)) {
        case RXRPC_CALL_SERVER_AWAIT_ACK:
                rxrpc_call_completed(call);
                break;
index 6491ca46a03fda6dc66e02e887ad08012acca14b..3e2f1a8e9c5b51bf90ce8679c06b6ec8a8958ea9 100644 (file)
@@ -527,7 +527,7 @@ try_again:
                msg->msg_namelen = len;
        }
 
-       switch (call->state) {
+       switch (READ_ONCE(call->state)) {
        case RXRPC_CALL_SERVER_ACCEPTING:
                ret = rxrpc_recvmsg_new_call(rx, call, msg, flags);
                break;
@@ -640,7 +640,7 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
 
        mutex_lock(&call->user_mutex);
 
-       switch (call->state) {
+       switch (READ_ONCE(call->state)) {
        case RXRPC_CALL_CLIENT_RECV_REPLY:
        case RXRPC_CALL_SERVER_RECV_REQUEST:
        case RXRPC_CALL_SERVER_ACK_REQUEST:
index bc2d3dcff9de76fcc42a20a3aeaec2305ebd2d6c..97ab214ca4118d7a451a4e56a916bd5809ae81f3 100644 (file)
@@ -488,6 +488,7 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
 int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
        __releases(&rx->sk.sk_lock.slock)
 {
+       enum rxrpc_call_state state;
        enum rxrpc_command cmd;
        struct rxrpc_call *call;
        unsigned long user_call_ID = 0;
@@ -526,13 +527,17 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                        return PTR_ERR(call);
                /* ... and we have the call lock. */
        } else {
-               ret = -EBUSY;
-               if (call->state == RXRPC_CALL_UNINITIALISED ||
-                   call->state == RXRPC_CALL_CLIENT_AWAIT_CONN ||
-                   call->state == RXRPC_CALL_SERVER_PREALLOC ||
-                   call->state == RXRPC_CALL_SERVER_SECURING ||
-                   call->state == RXRPC_CALL_SERVER_ACCEPTING)
+               switch (READ_ONCE(call->state)) {
+               case RXRPC_CALL_UNINITIALISED:
+               case RXRPC_CALL_CLIENT_AWAIT_CONN:
+               case RXRPC_CALL_SERVER_PREALLOC:
+               case RXRPC_CALL_SERVER_SECURING:
+               case RXRPC_CALL_SERVER_ACCEPTING:
+                       ret = -EBUSY;
                        goto error_release_sock;
+               default:
+                       break;
+               }
 
                ret = mutex_lock_interruptible(&call->user_mutex);
                release_sock(&rx->sk);
@@ -542,10 +547,11 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                }
        }
 
+       state = READ_ONCE(call->state);
        _debug("CALL %d USR %lx ST %d on CONN %p",
-              call->debug_id, call->user_call_ID, call->state, call->conn);
+              call->debug_id, call->user_call_ID, state, call->conn);
 
-       if (call->state >= RXRPC_CALL_COMPLETE) {
+       if (state >= RXRPC_CALL_COMPLETE) {
                /* it's too late for this call */
                ret = -ESHUTDOWN;
        } else if (cmd == RXRPC_CMD_SEND_ABORT) {
@@ -555,12 +561,12 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
        } else if (cmd != RXRPC_CMD_SEND_DATA) {
                ret = -EINVAL;
        } else if (rxrpc_is_client_call(call) &&
-                  call->state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
+                  state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
                /* request phase complete for this client call */
                ret = -EPROTO;
        } else if (rxrpc_is_service_call(call) &&
-                  call->state != RXRPC_CALL_SERVER_ACK_REQUEST &&
-                  call->state != RXRPC_CALL_SERVER_SEND_REPLY) {
+                  state != RXRPC_CALL_SERVER_ACK_REQUEST &&
+                  state != RXRPC_CALL_SERVER_SEND_REPLY) {
                /* Reply phase not begun or not complete for service call. */
                ret = -EPROTO;
        } else {
@@ -605,14 +611,21 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
        _debug("CALL %d USR %lx ST %d on CONN %p",
               call->debug_id, call->user_call_ID, call->state, call->conn);
 
-       if (call->state >= RXRPC_CALL_COMPLETE) {
-               ret = -ESHUTDOWN; /* it's too late for this call */
-       } else if (call->state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
-                  call->state != RXRPC_CALL_SERVER_ACK_REQUEST &&
-                  call->state != RXRPC_CALL_SERVER_SEND_REPLY) {
-               ret = -EPROTO; /* request phase complete for this client call */
-       } else {
+       switch (READ_ONCE(call->state)) {
+       case RXRPC_CALL_CLIENT_SEND_REQUEST:
+       case RXRPC_CALL_SERVER_ACK_REQUEST:
+       case RXRPC_CALL_SERVER_SEND_REPLY:
                ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len);
+               break;
+       case RXRPC_CALL_COMPLETE:
+               read_lock_bh(&call->state_lock);
+               ret = -call->error;
+               read_unlock_bh(&call->state_lock);
+               break;
+       default:
+                /* Request phase complete for this client call */
+               ret = -EPROTO;
+               break;
        }
 
        mutex_unlock(&call->user_mutex);
index ab80629099622c47933efb36662a323f98f66773..f9bb43c25697e70d18fe9bbba90f6e98dfe05759 100644 (file)
@@ -113,6 +113,9 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
        if (ret < 0)
                return ret;
 
+       if (!tb[TCA_CONNMARK_PARMS])
+               return -EINVAL;
+
        parm = nla_data(tb[TCA_CONNMARK_PARMS]);
 
        if (!tcf_hash_check(tn, parm->index, a, bind)) {
index 3b7074e2302487808dc1d16b01143d0b292ebe4e..c736627f8f4a0e0ff86db535ec95459a417e4ada 100644 (file)
@@ -228,7 +228,6 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,
 
        return skb->len;
 nla_put_failure:
-       rcu_read_unlock();
        nlmsg_trim(skb, b);
        return -1;
 }
index 802ac7c2e5e87eed1341ba4c09d3e5d70bc75876..5334e309f17f0ef4416dddcdc9278c14ecb5585d 100644 (file)
@@ -201,9 +201,13 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p);
 
        if (p->set_tc_index) {
+               int wlen = skb_network_offset(skb);
+
                switch (tc_skb_protocol(skb)) {
                case htons(ETH_P_IP):
-                       if (skb_cow_head(skb, sizeof(struct iphdr)))
+                       wlen += sizeof(struct iphdr);
+                       if (!pskb_may_pull(skb, wlen) ||
+                           skb_try_make_writable(skb, wlen))
                                goto drop;
 
                        skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
@@ -211,7 +215,9 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                        break;
 
                case htons(ETH_P_IPV6):
-                       if (skb_cow_head(skb, sizeof(struct ipv6hdr)))
+                       wlen += sizeof(struct ipv6hdr);
+                       if (!pskb_may_pull(skb, wlen) ||
+                           skb_try_make_writable(skb, wlen))
                                goto drop;
 
                        skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
index 2a6835b4562b61cff52425a530524f1c48bc7919..0439a1a6836784fd5096d85a4217980cb5c49690 100644 (file)
@@ -71,9 +71,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 {
        struct net *net = sock_net(sk);
        struct sctp_sock *sp;
-       int i;
        sctp_paramhdr_t *p;
-       int err;
+       int i;
 
        /* Retrieve the SCTP per socket area.  */
        sp = sctp_sk((struct sock *)sk);
@@ -264,8 +263,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        /* AUTH related initializations */
        INIT_LIST_HEAD(&asoc->endpoint_shared_keys);
-       err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp);
-       if (err)
+       if (sctp_auth_asoc_copy_shkeys(ep, asoc, gfp))
                goto fail_init;
 
        asoc->active_key_id = ep->active_key_id;
index 063baac5b9fe4048e9d7b41e848a33f0f73c61d4..961ee59f696a0b0a8b6c2bade0031a073dff53ad 100644 (file)
@@ -640,14 +640,15 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
 
 /* Create and initialize a new sk for the socket to be returned by accept(). */
 static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
-                                            struct sctp_association *asoc)
+                                            struct sctp_association *asoc,
+                                            bool kern)
 {
        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);
+       newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
        if (!newsk)
                goto out;
 
index 71ce6b945dcb54d831425bdb02e315a14dae69ef..1224421036b3e59c4dba1dd5d672923b55c7923c 100644 (file)
@@ -546,7 +546,6 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
        struct sctp_association *asoc = tp->asoc;
        struct sctp_chunk *chunk, *tmp;
        int pkt_count, gso = 0;
-       int confirm;
        struct dst_entry *dst;
        struct sk_buff *head;
        struct sctphdr *sh;
@@ -625,13 +624,13 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                        asoc->peer.last_sent_to = tp;
        }
        head->ignore_df = packet->ipfragok;
-       confirm = tp->dst_pending_confirm;
-       if (confirm)
+       if (tp->dst_pending_confirm)
                skb_set_dst_pending_confirm(head, 1);
        /* neighbour should be confirmed on successful transmission or
         * positive error
         */
-       if (tp->af_specific->sctp_xmit(head, tp) >= 0 && confirm)
+       if (tp->af_specific->sctp_xmit(head, tp) >= 0 &&
+           tp->dst_pending_confirm)
                tp->dst_pending_confirm = 0;
 
 out:
index db352e5d61f8980dc461a162959643d872997217..025ccff670720bd38b9cc9bd995b87e134c9f931 100644 (file)
@@ -382,17 +382,18 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
 }
 
 static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
-                                   struct sctp_sndrcvinfo *sinfo,
-                                   struct list_head *queue, int msg_len)
+                                   struct sctp_sndrcvinfo *sinfo, int msg_len)
 {
+       struct sctp_outq *q = &asoc->outqueue;
        struct sctp_chunk *chk, *temp;
 
-       list_for_each_entry_safe(chk, temp, queue, list) {
+       list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) {
                if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
                    chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
                        continue;
 
                list_del_init(&chk->list);
+               q->out_qlen -= chk->skb->len;
                asoc->sent_cnt_removable--;
                asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
 
@@ -431,9 +432,7 @@ void sctp_prsctp_prune(struct sctp_association *asoc,
                        return;
        }
 
-       sctp_prsctp_prune_unsent(asoc, sinfo,
-                                &asoc->outqueue.out_chunk_list,
-                                msg_len);
+       sctp_prsctp_prune_unsent(asoc, sinfo, msg_len);
 }
 
 /* Mark all the eligible packets on a transport for retransmission.  */
index 1b6d4574d2b02a2877caba604bb549352a0f0470..989a900383b57c57590bff37e3aee7426fb0b156 100644 (file)
@@ -575,10 +575,11 @@ static int sctp_v4_is_ce(const struct sk_buff *skb)
 
 /* Create and initialize a new sk for the socket returned by accept(). */
 static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
-                                            struct sctp_association *asoc)
+                                            struct sctp_association *asoc,
+                                            bool kern)
 {
        struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
-                       sk->sk_prot, 0);
+                       sk->sk_prot, kern);
        struct inet_sock *newinet;
 
        if (!newsk)
index 6f0a9be50f5055fd7efa29bb8b183cc37b23b25f..0f378ea2ae38828d75dc215abdbc258e75cec431 100644 (file)
@@ -4116,7 +4116,7 @@ static int sctp_disconnect(struct sock *sk, int flags)
  * descriptor will be returned from accept() to represent the newly
  * formed association.
  */
-static struct sock *sctp_accept(struct sock *sk, int flags, int *err)
+static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern)
 {
        struct sctp_sock *sp;
        struct sctp_endpoint *ep;
@@ -4151,7 +4151,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err)
         */
        asoc = list_entry(ep->asocs.next, struct sctp_association, asocs);
 
-       newsk = sp->pf->create_accept_sk(sk, asoc);
+       newsk = sp->pf->create_accept_sk(sk, asoc, kern);
        if (!newsk) {
                error = -ENOMEM;
                goto out;
index 85837ab90e8916e612d5dd0a21ef48c5e2c9e544..093803786eacf3388dc470a04c02293f60e4102e 100644 (file)
@@ -944,7 +944,7 @@ out:
 }
 
 static int smc_accept(struct socket *sock, struct socket *new_sock,
-                     int flags)
+                     int flags, bool kern)
 {
        struct sock *sk = sock->sk, *nsk;
        DECLARE_WAITQUEUE(wait, current);
index 2c1e8677ff2d4fdb2f29eaa6e06a7c323d27d981..985ef06792d6e54c69d296f3e15baf89be972f9c 100644 (file)
@@ -652,6 +652,16 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
 }
 EXPORT_SYMBOL(kernel_sendmsg);
 
+static bool skb_is_err_queue(const struct sk_buff *skb)
+{
+       /* pkt_type of skbs enqueued on the error queue are set to
+        * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
+        * in recvmsg, since skbs received on a local socket will never
+        * have a pkt_type of PACKET_OUTGOING.
+        */
+       return skb->pkt_type == PACKET_OUTGOING;
+}
+
 /*
  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
  */
@@ -695,7 +705,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
                put_cmsg(msg, SOL_SOCKET,
                         SCM_TIMESTAMPING, sizeof(tss), &tss);
 
-               if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
+               if (skb_is_err_queue(skb) && skb->len &&
+                   SKB_EXT_ERR(skb)->opt_stats)
                        put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
                                 skb->len, skb->data);
        }
@@ -1506,7 +1517,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
        if (err)
                goto out_fd;
 
-       err = sock->ops->accept(sock, newsock, sock->file->f_flags);
+       err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
        if (err < 0)
                goto out_fd;
 
@@ -1731,6 +1742,7 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
        /* We assume all kernel code knows the size of sockaddr_storage */
        msg.msg_namelen = 0;
        msg.msg_iocb = NULL;
+       msg.msg_flags = 0;
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        err = sock_recvmsg(sock, &msg, flags);
@@ -3238,7 +3250,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
        if (err < 0)
                goto done;
 
-       err = sock->ops->accept(sock, *newsock, flags);
+       err = sock->ops->accept(sock, *newsock, flags, true);
        if (err < 0) {
                sock_release(*newsock);
                *newsock = NULL;
index 81cd31acf690f41573e5fedd9b837376543f5ce9..3b332b395045b5b0ad07bc13a30db1420d7f7082 100644 (file)
@@ -503,7 +503,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
        struct ib_cq *sendcq, *recvcq;
        int rc;
 
-       max_sge = min(ia->ri_device->attrs.max_sge, RPCRDMA_MAX_SEND_SGES);
+       max_sge = min_t(unsigned int, ia->ri_device->attrs.max_sge,
+                       RPCRDMA_MAX_SEND_SGES);
        if (max_sge < RPCRDMA_MIN_SEND_SGES) {
                pr_warn("rpcrdma: HCA provides only %d send SGEs\n", max_sge);
                return -ENOMEM;
index 43e4045e72bc00cfbc9db6c1bf987a46e272969b..7130e73bd42c21758e88b24b875da4bd97b3c4d2 100644 (file)
@@ -115,7 +115,8 @@ static void tipc_data_ready(struct sock *sk);
 static void tipc_write_space(struct sock *sk);
 static void tipc_sock_destruct(struct sock *sk);
 static int tipc_release(struct socket *sock);
-static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags);
+static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
+                      bool kern);
 static void tipc_sk_timeout(unsigned long data);
 static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
                           struct tipc_name_seq const *seq);
@@ -2029,7 +2030,8 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo)
  *
  * Returns 0 on success, errno otherwise
  */
-static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
+static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
+                      bool kern)
 {
        struct sock *new_sk, *sk = sock->sk;
        struct sk_buff *buf;
@@ -2051,7 +2053,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
 
        buf = skb_peek(&sk->sk_receive_queue);
 
-       res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 0);
+       res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, kern);
        if (res)
                goto exit;
        security_sk_clone(sock->sk, new_sock->sk);
index 9d94e65d0894183b4af94ed24e84b94c0478b551..271cd66e4b3b66534d8686bec94132bc9737314e 100644 (file)
@@ -141,6 +141,11 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
 static void tipc_subscrp_timeout(unsigned long data)
 {
        struct tipc_subscription *sub = (struct tipc_subscription *)data;
+       struct tipc_subscriber *subscriber = sub->subscriber;
+
+       spin_lock_bh(&subscriber->lock);
+       tipc_nametbl_unsubscribe(sub);
+       spin_unlock_bh(&subscriber->lock);
 
        /* Notify subscriber of timeout */
        tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
@@ -173,7 +178,6 @@ static void tipc_subscrp_kref_release(struct kref *kref)
        struct tipc_subscriber *subscriber = sub->subscriber;
 
        spin_lock_bh(&subscriber->lock);
-       tipc_nametbl_unsubscribe(sub);
        list_del(&sub->subscrp_list);
        atomic_dec(&tn->subscription_count);
        spin_unlock_bh(&subscriber->lock);
@@ -205,6 +209,7 @@ static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber,
                if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr)))
                        continue;
 
+               tipc_nametbl_unsubscribe(sub);
                tipc_subscrp_get(sub);
                spin_unlock_bh(&subscriber->lock);
                tipc_subscrp_delete(sub);
index ee37b390260a62f026f08e3da827ae45666bc2a6..928691c434087e8ff72b84fc6515539115c0509b 100644 (file)
@@ -636,7 +636,7 @@ static int unix_bind(struct socket *, struct sockaddr *, int);
 static int unix_stream_connect(struct socket *, struct sockaddr *,
                               int addr_len, int flags);
 static int unix_socketpair(struct socket *, struct socket *);
-static int unix_accept(struct socket *, struct socket *, int);
+static int unix_accept(struct socket *, struct socket *, int, bool);
 static int unix_getname(struct socket *, struct sockaddr *, int *, int);
 static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
 static unsigned int unix_dgram_poll(struct file *, struct socket *,
@@ -1402,7 +1402,8 @@ static void unix_sock_inherit_flags(const struct socket *old,
                set_bit(SOCK_PASSSEC, &new->flags);
 }
 
-static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
+static int unix_accept(struct socket *sock, struct socket *newsock, int flags,
+                      bool kern)
 {
        struct sock *sk = sock->sk;
        struct sock *tsk;
index 6a0d48525fcf9a71f54bb43495b200b300f5341e..c36757e728442bb936c17f8a975b420f5f8a5972 100644 (file)
@@ -146,6 +146,7 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
        if (s) {
                struct unix_sock *u = unix_sk(s);
 
+               BUG_ON(!atomic_long_read(&u->inflight));
                BUG_ON(list_empty(&u->link));
 
                if (atomic_long_dec_and_test(&u->inflight))
@@ -341,6 +342,14 @@ void unix_gc(void)
        }
        list_del(&cursor);
 
+       /* Now gc_candidates contains only garbage.  Restore original
+        * inflight counters for these as well, and remove the skbuffs
+        * which are creating the cycle(s).
+        */
+       skb_queue_head_init(&hitlist);
+       list_for_each_entry(u, &gc_candidates, link)
+               scan_children(&u->sk, inc_inflight, &hitlist);
+
        /* not_cycle_list contains those sockets which do not make up a
         * cycle.  Restore these to the inflight list.
         */
@@ -350,14 +359,6 @@ void unix_gc(void)
                list_move_tail(&u->link, &gc_inflight_list);
        }
 
-       /* Now gc_candidates contains only garbage.  Restore original
-        * inflight counters for these as well, and remove the skbuffs
-        * which are creating the cycle(s).
-        */
-       skb_queue_head_init(&hitlist);
-       list_for_each_entry(u, &gc_candidates, link)
-       scan_children(&u->sk, inc_inflight, &hitlist);
-
        spin_unlock(&unix_gc_lock);
 
        /* Here we are. Hitlist is filled. Die. */
index 9192ead6675114128817267926befe23f7cc1111..6f7f6757ceefb500551fafbf40c462835c4baf88 100644 (file)
@@ -1102,10 +1102,19 @@ static const struct proto_ops vsock_dgram_ops = {
        .sendpage = sock_no_sendpage,
 };
 
+static int vsock_transport_cancel_pkt(struct vsock_sock *vsk)
+{
+       if (!transport->cancel_pkt)
+               return -EOPNOTSUPP;
+
+       return transport->cancel_pkt(vsk);
+}
+
 static void vsock_connect_timeout(struct work_struct *work)
 {
        struct sock *sk;
        struct vsock_sock *vsk;
+       int cancel = 0;
 
        vsk = container_of(work, struct vsock_sock, dwork.work);
        sk = sk_vsock(vsk);
@@ -1116,8 +1125,11 @@ static void vsock_connect_timeout(struct work_struct *work)
                sk->sk_state = SS_UNCONNECTED;
                sk->sk_err = ETIMEDOUT;
                sk->sk_error_report(sk);
+               cancel = 1;
        }
        release_sock(sk);
+       if (cancel)
+               vsock_transport_cancel_pkt(vsk);
 
        sock_put(sk);
 }
@@ -1224,11 +1236,13 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
                        err = sock_intr_errno(timeout);
                        sk->sk_state = SS_UNCONNECTED;
                        sock->state = SS_UNCONNECTED;
+                       vsock_transport_cancel_pkt(vsk);
                        goto out_wait;
                } else if (timeout == 0) {
                        err = -ETIMEDOUT;
                        sk->sk_state = SS_UNCONNECTED;
                        sock->state = SS_UNCONNECTED;
+                       vsock_transport_cancel_pkt(vsk);
                        goto out_wait;
                }
 
@@ -1250,7 +1264,8 @@ out:
        return err;
 }
 
-static int vsock_accept(struct socket *sock, struct socket *newsock, int flags)
+static int vsock_accept(struct socket *sock, struct socket *newsock, int flags,
+                       bool kern)
 {
        struct sock *listener;
        int err;
index 9d24c0e958b18e614e30b24c0fcfbbe2152941f3..68675a151f22b8b63c02b25a67b833d9a6046d84 100644 (file)
@@ -213,6 +213,47 @@ virtio_transport_send_pkt(struct virtio_vsock_pkt *pkt)
        return len;
 }
 
+static int
+virtio_transport_cancel_pkt(struct vsock_sock *vsk)
+{
+       struct virtio_vsock *vsock;
+       struct virtio_vsock_pkt *pkt, *n;
+       int cnt = 0;
+       LIST_HEAD(freeme);
+
+       vsock = virtio_vsock_get();
+       if (!vsock) {
+               return -ENODEV;
+       }
+
+       spin_lock_bh(&vsock->send_pkt_list_lock);
+       list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) {
+               if (pkt->vsk != vsk)
+                       continue;
+               list_move(&pkt->list, &freeme);
+       }
+       spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+       list_for_each_entry_safe(pkt, n, &freeme, list) {
+               if (pkt->reply)
+                       cnt++;
+               list_del(&pkt->list);
+               virtio_transport_free_pkt(pkt);
+       }
+
+       if (cnt) {
+               struct virtqueue *rx_vq = vsock->vqs[VSOCK_VQ_RX];
+               int new_cnt;
+
+               new_cnt = atomic_sub_return(cnt, &vsock->queued_replies);
+               if (new_cnt + cnt >= virtqueue_get_vring_size(rx_vq) &&
+                   new_cnt < virtqueue_get_vring_size(rx_vq))
+                       queue_work(virtio_vsock_workqueue, &vsock->rx_work);
+       }
+
+       return 0;
+}
+
 static void virtio_vsock_rx_fill(struct virtio_vsock *vsock)
 {
        int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE;
@@ -462,6 +503,7 @@ static struct virtio_transport virtio_transport = {
                .release                  = virtio_transport_release,
                .connect                  = virtio_transport_connect,
                .shutdown                 = virtio_transport_shutdown,
+               .cancel_pkt               = virtio_transport_cancel_pkt,
 
                .dgram_bind               = virtio_transport_dgram_bind,
                .dgram_dequeue            = virtio_transport_dgram_dequeue,
index 8d592a45b59786746d186e12d0c362d07c30bdac..af087b44ceea2311e53060e2442b4af2024bb037 100644 (file)
@@ -58,6 +58,7 @@ virtio_transport_alloc_pkt(struct virtio_vsock_pkt_info *info,
        pkt->len                = len;
        pkt->hdr.len            = cpu_to_le32(len);
        pkt->reply              = info->reply;
+       pkt->vsk                = info->vsk;
 
        if (info->msg && len > 0) {
                pkt->buf = kmalloc(len, GFP_KERNEL);
@@ -180,6 +181,7 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,
        struct virtio_vsock_pkt_info info = {
                .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE,
                .type = type,
+               .vsk = vsk,
        };
 
        return virtio_transport_send_pkt_info(vsk, &info);
@@ -519,6 +521,7 @@ int virtio_transport_connect(struct vsock_sock *vsk)
        struct virtio_vsock_pkt_info info = {
                .op = VIRTIO_VSOCK_OP_REQUEST,
                .type = VIRTIO_VSOCK_TYPE_STREAM,
+               .vsk = vsk,
        };
 
        return virtio_transport_send_pkt_info(vsk, &info);
@@ -534,6 +537,7 @@ int virtio_transport_shutdown(struct vsock_sock *vsk, int mode)
                          VIRTIO_VSOCK_SHUTDOWN_RCV : 0) |
                         (mode & SEND_SHUTDOWN ?
                          VIRTIO_VSOCK_SHUTDOWN_SEND : 0),
+               .vsk = vsk,
        };
 
        return virtio_transport_send_pkt_info(vsk, &info);
@@ -560,6 +564,7 @@ virtio_transport_stream_enqueue(struct vsock_sock *vsk,
                .type = VIRTIO_VSOCK_TYPE_STREAM,
                .msg = msg,
                .pkt_len = len,
+               .vsk = vsk,
        };
 
        return virtio_transport_send_pkt_info(vsk, &info);
@@ -581,6 +586,7 @@ static int virtio_transport_reset(struct vsock_sock *vsk,
                .op = VIRTIO_VSOCK_OP_RST,
                .type = VIRTIO_VSOCK_TYPE_STREAM,
                .reply = !!pkt,
+               .vsk = vsk,
        };
 
        /* Send RST only if the original pkt is not a RST pkt */
@@ -826,6 +832,7 @@ virtio_transport_send_response(struct vsock_sock *vsk,
                .remote_cid = le64_to_cpu(pkt->hdr.src_cid),
                .remote_port = le32_to_cpu(pkt->hdr.src_port),
                .reply = true,
+               .vsk = vsk,
        };
 
        return virtio_transport_send_pkt_info(vsk, &info);
index d7f8be4e321a32eba3a615aa69a860c212511625..2312dc2ffdb98b37b2909274c57eed68935267d7 100644 (file)
@@ -545,22 +545,18 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
 {
        int err;
 
-       rtnl_lock();
-
        if (!cb->args[0]) {
                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
                                  genl_family_attrbuf(&nl80211_fam),
                                  nl80211_fam.maxattr, nl80211_policy);
                if (err)
-                       goto out_unlock;
+                       return err;
 
                *wdev = __cfg80211_wdev_from_attrs(
                                        sock_net(skb->sk),
                                        genl_family_attrbuf(&nl80211_fam));
-               if (IS_ERR(*wdev)) {
-                       err = PTR_ERR(*wdev);
-                       goto out_unlock;
-               }
+               if (IS_ERR(*wdev))
+                       return PTR_ERR(*wdev);
                *rdev = wiphy_to_rdev((*wdev)->wiphy);
                /* 0 is the first index - add 1 to parse only once */
                cb->args[0] = (*rdev)->wiphy_idx + 1;
@@ -570,10 +566,8 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
                struct wireless_dev *tmp;
 
-               if (!wiphy) {
-                       err = -ENODEV;
-                       goto out_unlock;
-               }
+               if (!wiphy)
+                       return -ENODEV;
                *rdev = wiphy_to_rdev(wiphy);
                *wdev = NULL;
 
@@ -584,21 +578,11 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                        }
                }
 
-               if (!*wdev) {
-                       err = -ENODEV;
-                       goto out_unlock;
-               }
+               if (!*wdev)
+                       return -ENODEV;
        }
 
        return 0;
- out_unlock:
-       rtnl_unlock();
-       return err;
-}
-
-static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
-{
-       rtnl_unlock();
 }
 
 /* IE validation */
@@ -2608,17 +2592,17 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
        int filter_wiphy = -1;
        struct cfg80211_registered_device *rdev;
        struct wireless_dev *wdev;
+       int ret;
 
        rtnl_lock();
        if (!cb->args[2]) {
                struct nl80211_dump_wiphy_state state = {
                        .filter_wiphy = -1,
                };
-               int ret;
 
                ret = nl80211_dump_wiphy_parse(skb, cb, &state);
                if (ret)
-                       return ret;
+                       goto out_unlock;
 
                filter_wiphy = state.filter_wiphy;
 
@@ -2663,12 +2647,14 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
                wp_idx++;
        }
  out:
-       rtnl_unlock();
-
        cb->args[0] = wp_idx;
        cb->args[1] = if_idx;
 
-       return skb->len;
+       ret = skb->len;
+ out_unlock:
+       rtnl_unlock();
+
+       return ret;
 }
 
 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
@@ -4452,9 +4438,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
        int sta_idx = cb->args[2];
        int err;
 
+       rtnl_lock();
        err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
        if (err)
-               return err;
+               goto out_err;
 
        if (!wdev->netdev) {
                err = -EINVAL;
@@ -4489,7 +4476,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
        cb->args[2] = sta_idx;
        err = skb->len;
  out_err:
-       nl80211_finish_wdev_dump(rdev);
+       rtnl_unlock();
 
        return err;
 }
@@ -5275,9 +5262,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
        int path_idx = cb->args[2];
        int err;
 
+       rtnl_lock();
        err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
        if (err)
-               return err;
+               goto out_err;
 
        if (!rdev->ops->dump_mpath) {
                err = -EOPNOTSUPP;
@@ -5310,7 +5298,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
        cb->args[2] = path_idx;
        err = skb->len;
  out_err:
-       nl80211_finish_wdev_dump(rdev);
+       rtnl_unlock();
        return err;
 }
 
@@ -5470,9 +5458,10 @@ static int nl80211_dump_mpp(struct sk_buff *skb,
        int path_idx = cb->args[2];
        int err;
 
+       rtnl_lock();
        err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
        if (err)
-               return err;
+               goto out_err;
 
        if (!rdev->ops->dump_mpp) {
                err = -EOPNOTSUPP;
@@ -5505,7 +5494,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb,
        cb->args[2] = path_idx;
        err = skb->len;
  out_err:
-       nl80211_finish_wdev_dump(rdev);
+       rtnl_unlock();
        return err;
 }
 
@@ -7674,9 +7663,12 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
        int start = cb->args[2], idx = 0;
        int err;
 
+       rtnl_lock();
        err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
-       if (err)
+       if (err) {
+               rtnl_unlock();
                return err;
+       }
 
        wdev_lock(wdev);
        spin_lock_bh(&rdev->bss_lock);
@@ -7699,7 +7691,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
        wdev_unlock(wdev);
 
        cb->args[2] = idx;
-       nl80211_finish_wdev_dump(rdev);
+       rtnl_unlock();
 
        return skb->len;
 }
@@ -7784,9 +7776,10 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
        int res;
        bool radio_stats;
 
+       rtnl_lock();
        res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
        if (res)
-               return res;
+               goto out_err;
 
        /* prepare_wdev_dump parsed the attributes */
        radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
@@ -7827,7 +7820,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
        cb->args[2] = survey_idx;
        res = skb->len;
  out_err:
-       nl80211_finish_wdev_dump(rdev);
+       rtnl_unlock();
        return res;
 }
 
@@ -11508,17 +11501,13 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
        void *data = NULL;
        unsigned int data_len = 0;
 
-       rtnl_lock();
-
        if (cb->args[0]) {
                /* subtract the 1 again here */
                struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
                struct wireless_dev *tmp;
 
-               if (!wiphy) {
-                       err = -ENODEV;
-                       goto out_unlock;
-               }
+               if (!wiphy)
+                       return -ENODEV;
                *rdev = wiphy_to_rdev(wiphy);
                *wdev = NULL;
 
@@ -11538,23 +11527,19 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
        err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
                          attrbuf, nl80211_fam.maxattr, nl80211_policy);
        if (err)
-               goto out_unlock;
+               return err;
 
        if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
-           !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
-               err = -EINVAL;
-               goto out_unlock;
-       }
+           !attrbuf[NL80211_ATTR_VENDOR_SUBCMD])
+               return -EINVAL;
 
        *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
        if (IS_ERR(*wdev))
                *wdev = NULL;
 
        *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
-       if (IS_ERR(*rdev)) {
-               err = PTR_ERR(*rdev);
-               goto out_unlock;
-       }
+       if (IS_ERR(*rdev))
+               return PTR_ERR(*rdev);
 
        vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
        subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
@@ -11567,19 +11552,15 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
                if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
                        continue;
 
-               if (!vcmd->dumpit) {
-                       err = -EOPNOTSUPP;
-                       goto out_unlock;
-               }
+               if (!vcmd->dumpit)
+                       return -EOPNOTSUPP;
 
                vcmd_idx = i;
                break;
        }
 
-       if (vcmd_idx < 0) {
-               err = -EOPNOTSUPP;
-               goto out_unlock;
-       }
+       if (vcmd_idx < 0)
+               return -EOPNOTSUPP;
 
        if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
                data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
@@ -11596,9 +11577,6 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
 
        /* keep rtnl locked in successful case */
        return 0;
- out_unlock:
-       rtnl_unlock();
-       return err;
 }
 
 static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
@@ -11613,9 +11591,10 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
        int err;
        struct nlattr *vendor_data;
 
+       rtnl_lock();
        err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
        if (err)
-               return err;
+               goto out;
 
        vcmd_idx = cb->args[2];
        data = (void *)cb->args[3];
@@ -11624,15 +11603,21 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
 
        if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
                           WIPHY_VENDOR_CMD_NEED_NETDEV)) {
-               if (!wdev)
-                       return -EINVAL;
+               if (!wdev) {
+                       err = -EINVAL;
+                       goto out;
+               }
                if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
-                   !wdev->netdev)
-                       return -EINVAL;
+                   !wdev->netdev) {
+                       err = -EINVAL;
+                       goto out;
+               }
 
                if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
-                       if (!wdev_running(wdev))
-                               return -ENETDOWN;
+                       if (!wdev_running(wdev)) {
+                               err = -ENETDOWN;
+                               goto out;
+                       }
                }
        }
 
index fd28a49dbe8f0c99bb798acec314c63084fc22c6..8b911c29860e79f21b0ac8e1d3a80ed373fd537e 100644 (file)
@@ -852,7 +852,8 @@ static int x25_wait_for_data(struct sock *sk, long timeout)
        return rc;
 }
 
-static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
+static int x25_accept(struct socket *sock, struct socket *newsock, int flags,
+                     bool kern)
 {
        struct sock *sk = sock->sk;
        struct sock *newsk;
index 0806dccdf5078451e0dd9c5b5573d040ab21c831..236cbbc0ab9cfff05cd027ffb0dc56aa15e61033 100644 (file)
@@ -1243,7 +1243,7 @@ static inline int policy_to_flow_dir(int dir)
 }
 
 static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
-                                                const struct flowi *fl)
+                                                const struct flowi *fl, u16 family)
 {
        struct xfrm_policy *pol;
 
@@ -1251,8 +1251,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
  again:
        pol = rcu_dereference(sk->sk_policy[dir]);
        if (pol != NULL) {
-               bool match = xfrm_selector_match(&pol->selector, fl,
-                                                sk->sk_family);
+               bool match = xfrm_selector_match(&pol->selector, fl, family);
                int err = 0;
 
                if (match) {
@@ -2239,7 +2238,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
        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);
+               pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family);
                err = xfrm_expand_policies(fl, family, pols,
                                           &num_pols, &num_xfrms);
                if (err < 0)
@@ -2518,7 +2517,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);
+               pol = xfrm_sk_policy_lookup(sk, dir, &fl, family);
                if (IS_ERR(pol)) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
                        return 0;
@@ -3069,6 +3068,11 @@ static int __net_init xfrm_net_init(struct net *net)
 {
        int rv;
 
+       /* Initialize the per-net locks here */
+       spin_lock_init(&net->xfrm.xfrm_state_lock);
+       spin_lock_init(&net->xfrm.xfrm_policy_lock);
+       mutex_init(&net->xfrm.xfrm_cfg_mutex);
+
        rv = xfrm_statistics_init(net);
        if (rv < 0)
                goto out_statistics;
@@ -3085,11 +3089,6 @@ static int __net_init xfrm_net_init(struct net *net)
        if (rv < 0)
                goto out;
 
-       /* Initialize the per-net locks here */
-       spin_lock_init(&net->xfrm.xfrm_state_lock);
-       spin_lock_init(&net->xfrm.xfrm_policy_lock);
-       mutex_init(&net->xfrm.xfrm_cfg_mutex);
-
        return 0;
 
 out:
index 4c935202ce23be4fc57c9d79c3fe0a160d9b8a89..f3b1d7f50b81156d4c29c5c0958a884e9292bbae 100644 (file)
@@ -1832,6 +1832,7 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
             info->output_pool != client->pool->size)) {
                if (snd_seq_write_pool_allocated(client)) {
                        /* remove all existing cells */
+                       snd_seq_pool_mark_closing(client->pool);
                        snd_seq_queue_client_leave_cells(client->number);
                        snd_seq_pool_done(client->pool);
                }
index 448efd4e980edf97138b43b6263a9909d07c076a..33980d1c803796a3a77cf2ee69c35a9b5fcf1c9e 100644 (file)
@@ -72,6 +72,9 @@ void snd_seq_fifo_delete(struct snd_seq_fifo **fifo)
                return;
        *fifo = NULL;
 
+       if (f->pool)
+               snd_seq_pool_mark_closing(f->pool);
+
        snd_seq_fifo_clear(f);
 
        /* wake up clients if any */
index 1a1acf3ddda4c9aeb022548b9438498e0f036762..d4c61ec9be13d7389addd27bc70acf58bda2eecc 100644 (file)
@@ -415,6 +415,18 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
        return 0;
 }
 
+/* refuse the further insertion to the pool */
+void snd_seq_pool_mark_closing(struct snd_seq_pool *pool)
+{
+       unsigned long flags;
+
+       if (snd_BUG_ON(!pool))
+               return;
+       spin_lock_irqsave(&pool->lock, flags);
+       pool->closing = 1;
+       spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 /* remove events */
 int snd_seq_pool_done(struct snd_seq_pool *pool)
 {
@@ -425,10 +437,6 @@ int snd_seq_pool_done(struct snd_seq_pool *pool)
                return -EINVAL;
 
        /* wait for closing all threads */
-       spin_lock_irqsave(&pool->lock, flags);
-       pool->closing = 1;
-       spin_unlock_irqrestore(&pool->lock, flags);
-
        if (waitqueue_active(&pool->output_sleep))
                wake_up(&pool->output_sleep);
 
@@ -485,6 +493,7 @@ int snd_seq_pool_delete(struct snd_seq_pool **ppool)
        *ppool = NULL;
        if (pool == NULL)
                return 0;
+       snd_seq_pool_mark_closing(pool);
        snd_seq_pool_done(pool);
        kfree(pool);
        return 0;
index 4a2ec779b8a701b1aba2402e9de583878f7a39ca..32f959c17786d9ac8c071ba0e6fd070dc06da78b 100644 (file)
@@ -84,6 +84,7 @@ static inline int snd_seq_total_cells(struct snd_seq_pool *pool)
 int snd_seq_pool_init(struct snd_seq_pool *pool);
 
 /* done pool - free events */
+void snd_seq_pool_mark_closing(struct snd_seq_pool *pool);
 int snd_seq_pool_done(struct snd_seq_pool *pool);
 
 /* create pool */
index ab4cdab5cfa57abf3db2a8da806d0bf7031fed67..79edd88d5cd08398afb86c63b3d32b025162164e 100644 (file)
@@ -1905,7 +1905,7 @@ static int hw_card_start(struct hw *hw)
                return err;
 
        /* Set DMA transfer mask */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
+       if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
                dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
        } else {
                dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
index c15c51bea26d0afdcc6d8c806993754eaaa2e031..69266b8ea2ad7b498097c4bc231fbad6e55ff37e 100644 (file)
@@ -261,6 +261,7 @@ enum {
        CXT_FIXUP_HP_530,
        CXT_FIXUP_CAP_MIX_AMP_5047,
        CXT_FIXUP_MUTE_LED_EAPD,
+       CXT_FIXUP_HP_DOCK,
        CXT_FIXUP_HP_SPECTRE,
        CXT_FIXUP_HP_GATE_MIC,
 };
@@ -778,6 +779,14 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_mute_led_eapd,
        },
+       [CXT_FIXUP_HP_DOCK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x16, 0x21011020 }, /* line-out */
+                       { 0x18, 0x2181103f }, /* line-in */
+                       { }
+               }
+       },
        [CXT_FIXUP_HP_SPECTRE] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -839,6 +848,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
        SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
+       SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
        SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
        SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
@@ -871,6 +881,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
        { .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" },
        { .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" },
        { .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" },
+       { .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" },
        {}
 };
 
index 4e112221d825462ef7e1ae38c092e40e58667f38..7f989898cbd9aa6fcf16360f7cd8b48d6f87e681 100644 (file)
@@ -4847,6 +4847,7 @@ enum {
        ALC286_FIXUP_HP_GPIO_LED,
        ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY,
        ALC280_FIXUP_HP_DOCK_PINS,
+       ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED,
        ALC280_FIXUP_HP_9480M,
        ALC288_FIXUP_DELL_HEADSET_MODE,
        ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
@@ -5388,6 +5389,16 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC280_FIXUP_HP_GPIO4
        },
+       [ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1b, 0x21011020 }, /* line-out */
+                       { 0x18, 0x2181103f }, /* line-in */
+                       { },
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HP_GPIO_MIC1_LED
+       },
        [ALC280_FIXUP_HP_9480M] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc280_fixup_hp_9480m,
@@ -5647,7 +5658,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+       SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -5816,6 +5827,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, .name = "headset-mode-no-hp-mic"},
        {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
        {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
+       {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic1-led"},
        {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
        {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
        {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
@@ -6090,6 +6102,8 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                ALC295_STANDARD_PINS,
                {0x17, 0x21014040},
                {0x18, 0x21a19050}),
+       SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+               ALC295_STANDARD_PINS),
        SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC298_STANDARD_PINS,
                {0x17, 0x90170110}),
index 84c8f8fc597cd6046d17ee27839024b98329e33d..8adf4d1bd46e71237e6827f0eda8fc89e7b40ea1 100644 (file)
@@ -1,6 +1,7 @@
 menuconfig SND_X86
-       tristate "X86 sound devices"
+       bool "X86 sound devices"
        depends on X86
+       default y
        ---help---
          X86 sound devices that don't fall under SoC or PCI categories
 
diff --git a/tools/include/uapi/linux/bpf_perf_event.h b/tools/include/uapi/linux/bpf_perf_event.h
new file mode 100644 (file)
index 0000000..0674272
--- /dev/null
@@ -0,0 +1,18 @@
+/* Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#ifndef _UAPI__LINUX_BPF_PERF_EVENT_H__
+#define _UAPI__LINUX_BPF_PERF_EVENT_H__
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+struct bpf_perf_event_data {
+       struct pt_regs regs;
+       __u64 sample_period;
+};
+
+#endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */
index 70e389bc4af71aa8f18ae67507fb65b5093a7f98..9b4d8ba22fed85f1f2bef6f5d47dc88cbb4df5d1 100644 (file)
@@ -202,7 +202,7 @@ void symbols__fixup_end(struct rb_root *symbols)
 
        /* Last entry */
        if (curr->end == curr->start)
-               curr->end = roundup(curr->start, 4096);
+               curr->end = roundup(curr->start, 4096) + 4096;
 }
 
 void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
index 4b498265dae6dc3b52b35818453f2c895809b323..6a1ad58cb66f4ae6faaf4837e29c5f8b487f000c 100644 (file)
@@ -1,20 +1,23 @@
 LIBDIR := ../../../lib
-BPFOBJ := $(LIBDIR)/bpf/bpf.o
+BPFDIR := $(LIBDIR)/bpf
 
-CFLAGS += -Wall -O2 -lcap -I../../../include/uapi -I$(LIBDIR)
+CFLAGS += -Wall -O2 -I../../../include/uapi -I$(LIBDIR)
+LDLIBS += -lcap
 
 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map
 
 TEST_PROGS := test_kmod.sh
 
-.PHONY: all clean force
+include ../lib.mk
+
+BPFOBJ := $(OUTPUT)/bpf.o
+
+$(TEST_GEN_PROGS): $(BPFOBJ)
+
+.PHONY: force
 
 # force a rebuild of BPFOBJ when its dependencies are updated
 force:
 
 $(BPFOBJ): force
-       $(MAKE) -C $(dir $(BPFOBJ))
-
-$(test_objs): $(BPFOBJ)
-
-include ../lib.mk
+       $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/
index cada17ac00b8e6b5af37554ea8489be6ffc873a2..a0aa2009b0e0a81e65672eb795039a2172484c55 100644 (file)
@@ -80,8 +80,9 @@ static void test_hashmap(int task, void *data)
        assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
        key = 2;
        assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
-       key = 1;
-       assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
+       key = 3;
+       assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
+              errno == E2BIG);
 
        /* Check that key = 0 doesn't exist. */
        key = 0;
@@ -110,6 +111,24 @@ static void test_hashmap(int task, void *data)
        close(fd);
 }
 
+static void test_hashmap_sizes(int task, void *data)
+{
+       int fd, i, j;
+
+       for (i = 1; i <= 512; i <<= 1)
+               for (j = 1; j <= 1 << 18; j <<= 1) {
+                       fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
+                                           2, map_flags);
+                       if (fd < 0) {
+                               printf("Failed to create hashmap key=%d value=%d '%s'\n",
+                                      i, j, strerror(errno));
+                               exit(1);
+                       }
+                       close(fd);
+                       usleep(10); /* give kernel time to destroy */
+               }
+}
+
 static void test_hashmap_percpu(int task, void *data)
 {
        unsigned int nr_cpus = bpf_num_possible_cpus();
@@ -317,7 +336,10 @@ static void test_arraymap_percpu(int task, void *data)
 static void test_arraymap_percpu_many_keys(void)
 {
        unsigned int nr_cpus = bpf_num_possible_cpus();
-       unsigned int nr_keys = 20000;
+       /* nr_keys is not too large otherwise the test stresses percpu
+        * allocator more than anything else
+        */
+       unsigned int nr_keys = 2000;
        long values[nr_cpus];
        int key, fd, i;
 
@@ -419,6 +441,7 @@ static void test_map_stress(void)
 {
        run_parallel(100, test_hashmap, NULL);
        run_parallel(100, test_hashmap_percpu, NULL);
+       run_parallel(100, test_hashmap_sizes, NULL);
 
        run_parallel(100, test_arraymap, NULL);
        run_parallel(100, test_arraymap_percpu, NULL);
index e1f5b9eea1e874ab7f4698a1e20abc5588fe00bb..d1555e4240c0fb3066c459e05f76a6f91f3b66af 100644 (file)
@@ -8,6 +8,8 @@
  * License as published by the Free Software Foundation.
  */
 
+#include <asm/types.h>
+#include <linux/types.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -4583,10 +4585,12 @@ static bool is_admin(void)
        cap_flag_value_t sysadmin = CAP_CLEAR;
        const cap_value_t cap_val = CAP_SYS_ADMIN;
 
+#ifdef CAP_IS_SUPPORTED
        if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) {
                perror("cap_get_flag");
                return false;
        }
+#endif
        caps = cap_get_proc();
        if (!caps) {
                perror("cap_get_proc");
index d828bfb6ef2d9a55f5752352458bca0ab1958549..54064ced9e95b3c66e57748f82ddf65aca91e94b 100644 (file)
  */
 FUNC_START(load_vsx)
        li      r5,0
-       lxvx    vs20,r5,r3
+       lxvd2x  vs20,r5,r3
        addi    r5,r5,16
-       lxvx    vs21,r5,r3
+       lxvd2x  vs21,r5,r3
        addi    r5,r5,16
-       lxvx    vs22,r5,r3
+       lxvd2x  vs22,r5,r3
        addi    r5,r5,16
-       lxvx    vs23,r5,r3
+       lxvd2x  vs23,r5,r3
        addi    r5,r5,16
-       lxvx    vs24,r5,r3
+       lxvd2x  vs24,r5,r3
        addi    r5,r5,16
-       lxvx    vs25,r5,r3
+       lxvd2x  vs25,r5,r3
        addi    r5,r5,16
-       lxvx    vs26,r5,r3
+       lxvd2x  vs26,r5,r3
        addi    r5,r5,16
-       lxvx    vs27,r5,r3
+       lxvd2x  vs27,r5,r3
        addi    r5,r5,16
-       lxvx    vs28,r5,r3
+       lxvd2x  vs28,r5,r3
        addi    r5,r5,16
-       lxvx    vs29,r5,r3
+       lxvd2x  vs29,r5,r3
        addi    r5,r5,16
-       lxvx    vs30,r5,r3
+       lxvd2x  vs30,r5,r3
        addi    r5,r5,16
-       lxvx    vs31,r5,r3
+       lxvd2x  vs31,r5,r3
        blr
 FUNC_END(load_vsx)
 
 FUNC_START(store_vsx)
        li      r5,0
-       stxvx   vs20,r5,r3
+       stxvd2x vs20,r5,r3
        addi    r5,r5,16
-       stxvx   vs21,r5,r3
+       stxvd2x vs21,r5,r3
        addi    r5,r5,16
-       stxvx   vs22,r5,r3
+       stxvd2x vs22,r5,r3
        addi    r5,r5,16
-       stxvx   vs23,r5,r3
+       stxvd2x vs23,r5,r3
        addi    r5,r5,16
-       stxvx   vs24,r5,r3
+       stxvd2x vs24,r5,r3
        addi    r5,r5,16
-       stxvx   vs25,r5,r3
+       stxvd2x vs25,r5,r3
        addi    r5,r5,16
-       stxvx   vs26,r5,r3
+       stxvd2x vs26,r5,r3
        addi    r5,r5,16
-       stxvx   vs27,r5,r3
+       stxvd2x vs27,r5,r3
        addi    r5,r5,16
-       stxvx   vs28,r5,r3
+       stxvd2x vs28,r5,r3
        addi    r5,r5,16
-       stxvx   vs29,r5,r3
+       stxvd2x vs29,r5,r3
        addi    r5,r5,16
-       stxvx   vs30,r5,r3
+       stxvd2x vs30,r5,r3
        addi    r5,r5,16
-       stxvx   vs31,r5,r3
+       stxvd2x vs31,r5,r3
        blr
 FUNC_END(store_vsx)