Merge branch irq/misc-6.4 into irq/irqchip-next
authorMarc Zyngier <maz@kernel.org>
Fri, 21 Apr 2023 13:05:31 +0000 (14:05 +0100)
committerMarc Zyngier <maz@kernel.org>
Fri, 21 Apr 2023 13:05:31 +0000 (14:05 +0100)
* irq/misc-6.4:
  : .
  : Misc irqchip changes for 6.4:
  :
  : - Replace uses of of_find_property() with the more
  :   appropriate of_property_read_bool()
  :
  : - Make bcm-6345-l1 request its MMIO region
  :
  : - Add suspend support to the SiFive PLIC
  :
  : - Drop support for stih415, stih416 and stid127 platforms
  : .
  irqchip/st: Remove stih415/stih416 and stid127 platforms support
  irqchip/irq-sifive-plic: Add syscore callbacks for hibernation
  irqchip: Use of_property_read_bool() for boolean properties
  irqchip/bcm-6345-l1: Request memory region

Signed-off-by: Marc Zyngier <maz@kernel.org>
391 files changed:
.mailmap
Documentation/arm64/silicon-errata.rst
Documentation/networking/xdp-rx-metadata.rst
Documentation/usb/gadget_uvc.rst [new file with mode: 0644]
Documentation/usb/index.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/e60k02.dtsi
arch/arm/boot/dts/e70k02.dtsi
arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts
arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts
arch/arm/lib/uaccess_with_memcpy.c
arch/arm64/Kconfig
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-kbox-a-230-ls.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var1.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var2.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts
arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
arch/arm64/boot/dts/freescale/imx8mm-nitrogen-r2.dts
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx93.dtsi
arch/arm64/boot/dts/nvidia/tegra194.dtsi
arch/arm64/boot/dts/nvidia/tegra234.dtsi
arch/arm64/boot/dts/qcom/msm8916-thwc-uf896.dts
arch/arm64/boot/dts/qcom/msm8916-thwc-ufi001c.dts
arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi
arch/arm64/boot/dts/qcom/sa8540p-ride.dts
arch/arm64/boot/dts/qcom/sc7280.dtsi
arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
arch/arm64/boot/dts/qcom/sc8280xp.dtsi
arch/arm64/boot/dts/qcom/sm6115.dtsi
arch/arm64/boot/dts/qcom/sm6375.dtsi
arch/arm64/boot/dts/qcom/sm8150.dtsi
arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish.dts
arch/arm64/boot/dts/qcom/sm8350.dtsi
arch/arm64/boot/dts/qcom/sm8450.dtsi
arch/arm64/boot/dts/qcom/sm8550.dtsi
arch/arm64/kernel/efi-header.S
arch/powerpc/include/asm/kasan.h
arch/powerpc/include/asm/string.h
arch/powerpc/kernel/prom_init_check.sh
arch/riscv/Kconfig
arch/riscv/Makefile
arch/riscv/include/asm/irq.h
arch/riscv/include/asm/sbi.h
arch/riscv/include/asm/smp.h
arch/riscv/include/asm/tlbflush.h
arch/riscv/kernel/Makefile
arch/riscv/kernel/cpu-hotplug.c
arch/riscv/kernel/irq.c
arch/riscv/kernel/sbi-ipi.c [new file with mode: 0644]
arch/riscv/kernel/sbi.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/smpboot.c
arch/riscv/mm/cacheflush.c
arch/riscv/mm/context.c
arch/riscv/mm/tlbflush.c
arch/x86/events/amd/core.c
arch/x86/kernel/fpu/xstate.c
arch/x86/mm/cpu_entry_area.c
arch/x86/xen/enlighten_pvh.c
crypto/asymmetric_keys/pkcs7_verify.c
crypto/asymmetric_keys/verify_pefile.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_thermal.c
drivers/acpi/resource.c
drivers/acpi/video_detect.c
drivers/atm/idt77252.c
drivers/block/ublk_drv.c
drivers/bluetooth/btintel.c
drivers/bluetooth/btintel.h
drivers/bluetooth/btqcomsmd.c
drivers/bluetooth/btsdio.c
drivers/bluetooth/btusb.c
drivers/bus/imx-weim.c
drivers/clocksource/timer-clint.c
drivers/firmware/arm_scmi/bus.c
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/mailbox.c
drivers/firmware/efi/earlycon.c
drivers/firmware/efi/efi-init.c
drivers/firmware/efi/libstub/Makefile.zboot
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/arm64.c
drivers/firmware/efi/libstub/efi-stub-entry.c
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/randomalloc.c
drivers/firmware/efi/libstub/screen_info.c
drivers/firmware/efi/libstub/smbios.c
drivers/firmware/efi/libstub/zboot-header.S
drivers/firmware/efi/libstub/zboot.c
drivers/firmware/efi/sysfb_efi.c
drivers/firmware/qcom_scm.c
drivers/firmware/smccc/smccc.c
drivers/firmware/smccc/soc_id.c
drivers/firmware/sysfb.c
drivers/firmware/sysfb_simplefb.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
drivers/gpu/drm/bridge/lontium-lt8912b.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/i915/display/intel_crtc.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_dmc.c
drivers/gpu/drm/i915/display/intel_fbdev.c
drivers/gpu/drm/i915/gt/intel_gt.c
drivers/gpu/drm/i915/gt/intel_gt_pm.c
drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
drivers/gpu/drm/i915/gt/intel_rc6.c
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
drivers/gpu/drm/i915/i915_active.c
drivers/gpu/drm/i915/i915_hwmon.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/host1x/dev.c
drivers/hwmon/hwmon.c
drivers/hwmon/it87.c
drivers/hwmon/peci/cputemp.c
drivers/hwmon/xgene-hwmon.c
drivers/i2c/busses/i2c-hisi.c
drivers/i2c/busses/i2c-imx-lpi2c.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-loongson-eiointc.c
drivers/irqchip/irq-loongson-pch-pic.c
drivers/irqchip/irq-riscv-intc.c
drivers/md/dm-crypt.c
drivers/md/dm-stats.c
drivers/md/dm-stats.h
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/net/dsa/b53/b53_mmap.c
drivers/net/dsa/mt7530.c
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/iavf/iavf_common.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_txrx.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_sriov.c
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/igbvf/vf.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
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_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
drivers/net/ethernet/mscc/ocelot_stats.c
drivers/net/ethernet/natsemi/sonic.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/am65-cpts.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_net.h
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/mdio/acpi_mdio.c
drivers/net/mdio/mdio-thunder.c
drivers/net/mdio/of_mdio.c
drivers/net/phy/mdio_devres.c
drivers/net/phy/phy.c
drivers/net/phy/sfp.c
drivers/net/usb/asix_devices.c
drivers/net/usb/lan78xx.c
drivers/net/usb/plusb.c
drivers/net/usb/smsc95xx.c
drivers/net/veth.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/marvell/mwifiex/pcie.c
drivers/net/wireless/marvell/mwifiex/sdio.c
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/nvme/host/core.c
drivers/nvme/host/ioctl.c
drivers/platform/chrome/cros_ec_chardev.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq24190_charger.c
drivers/power/supply/cros_usbpd-charger.c
drivers/power/supply/da9150-charger.c
drivers/power/supply/rk817_charger.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_devinfo.c
drivers/soc/qcom/llcc-qcom.c
drivers/soc/qcom/rmtfs_mem.c
drivers/tee/amdtee/core.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/thermal/thermal_sysfs.c
drivers/thunderbolt/debugfs.c
drivers/thunderbolt/nhi.c
drivers/thunderbolt/nhi_regs.h
drivers/thunderbolt/quirks.c
drivers/thunderbolt/retimer.c
drivers/thunderbolt/sb_regs.h
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/usb4.c
drivers/tty/hvc/hvc_xen.c
drivers/usb/cdns3/cdns3-pci-wrap.c
drivers/usb/cdns3/cdnsp-ep0.c
drivers/usb/cdns3/cdnsp-pci.c
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/core.c
drivers/usb/chipidea/otg.c
drivers/usb/dwc2/drd.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/u_audio.c
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/misc/onboard_usb_hub.h
drivers/usb/storage/unusual_uas.h
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi_acpi.c
drivers/vfio/pci/mlx5/main.c
fs/btrfs/block-group.c
fs/btrfs/free-space-cache.c
fs/btrfs/fs.h
fs/btrfs/inode.c
fs/btrfs/space-info.c
fs/btrfs/space-info.h
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/cifs/cached_dir.c
fs/cifs/cifs_debug.c
fs/cifs/cifsfs.c
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dfs.c
fs/cifs/dfs_cache.c
fs/cifs/file.c
fs/cifs/fs_context.h
fs/cifs/link.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2transport.c
fs/cifs/trace.h
fs/crypto/keyring.c
fs/gfs2/dentry.c
fs/ksmbd/auth.c
fs/ksmbd/connection.c
fs/ksmbd/connection.h
fs/ksmbd/smb2pdu.c
fs/ksmbd/smb_common.c
fs/ksmbd/smb_common.h
fs/ksmbd/transport_rdma.c
fs/ksmbd/transport_tcp.c
fs/lockd/clnt4xdr.c
fs/lockd/xdr4.c
fs/nfs/Kconfig
fs/nfs/dir.c
fs/nfs/read.c
fs/nfsd/Kconfig
fs/nfsd/vfs.c
fs/nilfs2/ioctl.c
fs/super.c
fs/verity/enable.c
fs/verity/verify.c
fs/xfs/Makefile
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/xfs_dahash_test.c [new file with mode: 0644]
fs/xfs/xfs_dahash_test.h [new file with mode: 0644]
fs/xfs/xfs_iomap.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
fs/zonefs/file.c
include/linux/acpi_mdio.h
include/linux/arm-smccc.h
include/linux/context_tracking.h
include/linux/context_tracking_state.h
include/linux/cpumask.h
include/linux/efi.h
include/linux/find.h
include/linux/io_uring.h
include/linux/irqchip/arm-gic.h
include/linux/lockd/xdr4.h
include/linux/nvme-tcp.h
include/linux/of_mdio.h
include/linux/percpu_counter.h
include/linux/stmmac.h
include/linux/sysfb.h
include/linux/thermal.h
include/net/bluetooth/hci_core.h
include/trace/events/mmap.h
init/main.c
io_uring/filetable.c
io_uring/net.c
io_uring/rsrc.c
io_uring/uring_cmd.c
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/entry/common.c
kernel/fork.c
kernel/kcsan/Makefile
kernel/sched/core.c
kernel/sched/fair.c
lib/dhry_run.c
lib/find_bit.c
lib/maple_tree.c
lib/percpu_counter.c
lib/test_maple_tree.c
mm/kfence/Makefile
mm/kfence/core.c
mm/ksm.c
mm/mmap.c
mm/mprotect.c
mm/page_alloc.c
mm/slab.c
mm/vmalloc.c
net/bluetooth/hci_core.c
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c
net/core/xdp.c
net/dsa/tag.c
net/dsa/tag_brcm.c
net/ipv4/ip_gre.c
net/ipv6/ip6_gre.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/rx.c
net/mac80211/util.c
net/mac80211/wme.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/xdp/xdp_umem.c
scripts/checksyscalls.sh
security/keys/request_key.c
tools/bootconfig/test-bootconfig.sh
tools/lib/bpf/libbpf_internal.h
tools/net/ynl/lib/ynl.py
tools/testing/selftests/bpf/prog_tests/uninit_stack.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/find_vma_fail1.c
tools/testing/selftests/bpf/progs/test_deny_namespace.c
tools/testing/selftests/bpf/progs/test_global_func10.c
tools/testing/selftests/bpf/progs/uninit_stack.c [new file with mode: 0644]
tools/testing/selftests/bpf/verifier/calls.c
tools/testing/selftests/bpf/verifier/helper_access_var_len.c
tools/testing/selftests/bpf/verifier/int_ptr.c
tools/testing/selftests/bpf/verifier/search_pruning.c
tools/testing/selftests/bpf/verifier/sock.c
tools/testing/selftests/bpf/verifier/spill_fill.c
tools/testing/selftests/bpf/verifier/var_off.c
tools/testing/selftests/mm/mdwe_test.c
tools/testing/selftests/x86/amx.c

index 317e51a..e2af78f 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -133,6 +133,8 @@ Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
 Domen Puncer <domen@coderock.org>
 Douglas Gilbert <dougg@torque.net>
 Ed L. Cashin <ecashin@coraid.com>
+Enric Balletbo i Serra <eballetbo@kernel.org> <enric.balletbo@collabora.com>
+Enric Balletbo i Serra <eballetbo@kernel.org> <eballetbo@iseebcn.com>
 Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com>
 Eugen Hristev <eugen.hristev@collabora.com> <eugen.hristev@microchip.com>
 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
@@ -379,6 +381,7 @@ Quentin Monnet <quentin@isovalent.com> <quentin.monnet@netronome.com>
 Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
 Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
 Rajeev Nandan <quic_rajeevny@quicinc.com> <rajeevny@codeaurora.org>
+Rajendra Nayak <quic_rjendra@quicinc.com> <rnayak@codeaurora.org>
 Rajesh Shah <rajesh.shah@intel.com>
 Ralf Baechle <ralf@linux-mips.org>
 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
@@ -387,6 +390,9 @@ Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
 Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
+Richard Leitner <richard.leitner@linux.dev> <dev@g0hl1n.net>
+Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
+Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
 Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
 Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
 Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
@@ -397,6 +403,7 @@ Ross Zwisler <zwisler@kernel.org> <ross.zwisler@linux.intel.com>
 Rudolf Marek <R.Marek@sh.cvut.cz>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Sachin P Sant <ssant@in.ibm.com>
+Sai Prakash Ranjan <quic_saipraka@quicinc.com> <saiprakash.ranjan@codeaurora.org>
 Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
 Sam Ravnborg <sam@mars.ravnborg.org>
 Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org>
@@ -437,6 +444,10 @@ Thomas Graf <tgraf@suug.ch>
 Thomas Körper <socketcan@esd.eu> <thomas.koerper@esd.eu>
 Thomas Pedersen <twp@codeaurora.org>
 Tiezhu Yang <yangtiezhu@loongson.cn> <kernelpatch@126.com>
+Tobias Klauser <tklauser@distanz.ch> <tobias.klauser@gmail.com>
+Tobias Klauser <tklauser@distanz.ch> <klto@zhaw.ch>
+Tobias Klauser <tklauser@distanz.ch> <tklauser@nuerscht.ch>
+Tobias Klauser <tklauser@distanz.ch> <tklauser@xenon.tklauser.home>
 Todor Tomov <todor.too@gmail.com> <todor.tomov@linaro.org>
 Tony Luck <tony.luck@intel.com>
 TripleX Chung <xxx.phy@gmail.com> <triplex@zh-kernel.org>
index ec5f889..9e311bc 100644 (file)
@@ -172,6 +172,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | Carmel Core     | N/A             | NVIDIA_CARMEL_CNP_ERRATUM   |
 +----------------+-----------------+-----------------+-----------------------------+
+| NVIDIA         | T241 GICv3/4.x  | T241-FABRIC-4   | N/A                         |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
 +----------------+-----------------+-----------------+-----------------------------+
@@ -205,6 +207,9 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | Qualcomm Tech. | Kryo4xx Gold    | N/A             | ARM64_ERRATUM_1286807       |
 +----------------+-----------------+-----------------+-----------------------------+
++----------------+-----------------+-----------------+-----------------------------+
+| Rockchip       | RK3588          | #3588001        | ROCKCHIP_ERRATUM_3588001    |
++----------------+-----------------+-----------------+-----------------------------+
 
 +----------------+-----------------+-----------------+-----------------------------+
 | Fujitsu        | A64FX           | E#010001        | FUJITSU_ERRATUM_010001      |
index aac63fc..25ce72a 100644 (file)
@@ -23,10 +23,13 @@ metadata is supported, this set will grow:
 An XDP program can use these kfuncs to read the metadata into stack
 variables for its own consumption. Or, to pass the metadata on to other
 consumers, an XDP program can store it into the metadata area carried
-ahead of the packet.
+ahead of the packet. Not all packets will necessary have the requested
+metadata available in which case the driver returns ``-ENODATA``.
 
 Not all kfuncs have to be implemented by the device driver; when not
-implemented, the default ones that return ``-EOPNOTSUPP`` will be used.
+implemented, the default ones that return ``-EOPNOTSUPP`` will be used
+to indicate the device driver have not implemented this kfunc.
+
 
 Within an XDP frame, the metadata layout (accessed via ``xdp_buff``) is
 as follows::
diff --git a/Documentation/usb/gadget_uvc.rst b/Documentation/usb/gadget_uvc.rst
new file mode 100644 (file)
index 0000000..6d22fac
--- /dev/null
@@ -0,0 +1,352 @@
+=======================
+Linux UVC Gadget Driver
+=======================
+
+Overview
+--------
+The UVC Gadget driver is a driver for hardware on the *device* side of a USB
+connection. It is intended to run on a Linux system that has USB device-side
+hardware such as boards with an OTG port.
+
+On the device system, once the driver is bound it appears as a V4L2 device with
+the output capability.
+
+On the host side (once connected via USB cable), a device running the UVC Gadget
+driver *and controlled by an appropriate userspace program* should appear as a UVC
+specification compliant camera, and function appropriately with any program
+designed to handle them. The userspace program running on the device system can
+queue image buffers from a variety of sources to be transmitted via the USB
+connection. Typically this would mean forwarding the buffers from a camera sensor
+peripheral, but the source of the buffer is entirely dependent on the userspace
+companion program.
+
+Configuring the device kernel
+-----------------------------
+The Kconfig options USB_CONFIGFS, USB_LIBCOMPOSITE, USB_CONFIGFS_F_UVC and
+USB_F_UVC must be selected to enable support for the UVC gadget.
+
+Configuring the gadget through configfs
+---------------------------------------
+The UVC Gadget expects to be configured through configfs using the UVC function.
+This allows a significant degree of flexibility, as many of a UVC device's
+settings can be controlled this way.
+
+Not all of the available attributes are described here. For a complete enumeration
+see Documentation/ABI/testing/configfs-usb-gadget-uvc
+
+Assumptions
+~~~~~~~~~~~
+This section assumes that you have mounted configfs at `/sys/kernel/config` and
+created a gadget as `/sys/kernel/config/usb_gadget/g1`.
+
+The UVC Function
+~~~~~~~~~~~~~~~~
+
+The first step is to create the UVC function:
+
+.. code-block:: bash
+
+       # These variables will be assumed throughout the rest of the document
+       CONFIGFS="/sys/kernel/config"
+       GADGET="$CONFIGFS/usb_gadget/g1"
+       FUNCTION="$GADGET/functions/uvc.0"
+
+       mkdir -p $FUNCTION
+
+Formats and Frames
+~~~~~~~~~~~~~~~~~~
+
+You must configure the gadget by telling it which formats you support, as well
+as the frame sizes and frame intervals that are supported for each format. In
+the current implementation there is no way for the gadget to refuse to set a
+format that the host instructs it to set, so it is important that this step is
+completed *accurately* to ensure that the host never asks for a format that
+can't be provided.
+
+Formats are created under the streaming/uncompressed and streaming/mjpeg configfs
+groups, with the framesizes created under the formats in the following
+structure:
+
+::
+
+       uvc.0 +
+             |
+             + streaming +
+                         |
+                         + mjpeg +
+                         |       |
+                         |       + mjpeg +
+                         |            |
+                         |            + 720p
+                         |            |
+                         |            + 1080p
+                         |
+                         + uncompressed +
+                                        |
+                                        + yuyv +
+                                               |
+                                               + 720p
+                                               |
+                                               + 1080p
+
+Each frame can then be configured with a width and height, plus the maximum
+buffer size required to store a single frame, and finally with the supported
+frame intervals for that format and framesize. Width and height are enumerated in
+units of pixels, frame interval in units of 100ns. To create the structure
+above with 2, 15 and 100 fps frameintervals for each framesize for example you
+might do:
+
+.. code-block:: bash
+
+       create_frame() {
+               # Example usage:
+               # create_frame <width> <height> <group> <format name>
+
+               WIDTH=$1
+               HEIGHT=$2
+               FORMAT=$3
+               NAME=$4
+
+               wdir=$FUNCTION/streaming/$FORMAT/$NAME/${HEIGHT}p
+
+               mkdir -p $wdir
+               echo $WIDTH > $wdir/wWidth
+               echo $HEIGHT > $wdir/wHeight
+               echo $(( $WIDTH * $HEIGHT * 2 )) > $wdir/dwMaxVideoFrameBufferSize
+               cat <<EOF > $wdir/dwFrameInterval
+       666666
+       100000
+       5000000
+       EOF
+       }
+
+       create_frame 1280 720 mjpeg mjpeg
+       create_frame 1920 1080 mjpeg mjpeg
+       create_frame 1280 720 uncompressed yuyv
+       create_frame 1920 1080 uncompressed yuyv
+
+The only uncompressed format currently supported is YUYV, which is detailed at
+Documentation/userspace-api/media/v4l/pixfmt-packed.yuv.rst.
+
+Color Matching Descriptors
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+It's possible to specify some colometry information for each format you create.
+This step is optional, and default information will be included if this step is
+skipped; those default values follow those defined in the Color Matching Descriptor
+section of the UVC specification.
+
+To create a Color Matching Descriptor, create a configfs item and set its three
+attributes to your desired settings and then link to it from the format you wish
+it to be associated with:
+
+.. code-block:: bash
+
+       # Create a new Color Matching Descriptor
+
+       mkdir $FUNCTION/streaming/color_matching/yuyv
+       pushd $FUNCTION/streaming/color_matching/yuyv
+
+       echo 1 > bColorPrimaries
+       echo 1 > bTransferCharacteristics
+       echo 4 > bMatrixCoefficients
+
+       popd
+
+       # Create a symlink to the Color Matching Descriptor from the format's config item
+       ln -s $FUNCTION/streaming/color_matching/yuyv $FUNCTION/streaming/uncompressed/yuyv
+
+For details about the valid values, consult the UVC specification. Note that a
+default color matching descriptor exists and is used by any format which does
+not have a link to a different Color Matching Descriptor. It's possible to
+change the attribute settings for the default descriptor, so bear in mind that if
+you do that you are altering the defaults for any format that does not link to
+a different one.
+
+
+Header linking
+~~~~~~~~~~~~~~
+
+The UVC specification requires that Format and Frame descriptors be preceded by
+Headers detailing things such as the number and cumulative size of the different
+Format descriptors that follow. This and similar operations are acheived in
+configfs by linking between the configfs item representing the header and the
+config items representing those other descriptors, in this manner:
+
+.. code-block:: bash
+
+       mkdir $FUNCTION/streaming/header/h
+
+       # This section links the format descriptors and their associated frames
+       # to the header
+       cd $FUNCTION/streaming/header/h
+       ln -s ../../uncompressed/yuyv
+       ln -s ../../mjpeg/mjpeg
+
+       # This section ensures that the header will be transmitted for each
+       # speed's set of descriptors. If support for a particular speed is not
+       # needed then it can be skipped here.
+       cd ../../class/fs
+       ln -s ../../header/h
+       cd ../../class/hs
+       ln -s ../../header/h
+       cd ../../class/ss
+       ln -s ../../header/h
+       cd ../../../control
+       mkdir header/h
+       ln -s header/h class/fs
+       ln -s header/h class/ss
+
+
+Extension Unit Support
+~~~~~~~~~~~~~~~~~~~~~~
+
+A UVC Extension Unit (XU) basically provides a distinct unit to which control set
+and get requests can be addressed. The meaning of those control requests is
+entirely implementation dependent, but may be used to control settings outside
+of the UVC specification (for example enabling or disabling video effects). An
+XU can be inserted into the UVC unit chain or left free-hanging.
+
+Configuring an extension unit involves creating an entry in the appropriate
+directory and setting its attributes appropriately, like so:
+
+.. code-block:: bash
+
+       mkdir $FUNCTION/control/extensions/xu.0
+       pushd $FUNCTION/control/extensions/xu.0
+
+       # Set the bUnitID of the Processing Unit as the source for this
+       # Extension Unit
+       echo 2 > baSourceID
+
+       # Set this XU as the source of the default output terminal. This inserts
+       # the XU into the UVC chain between the PU and OT such that the final
+       # chain is IT > PU > XU.0 > OT
+       cat bUnitID > ../../terminal/output/default/baSourceID
+
+       # Flag some controls as being available for use. The bmControl field is
+       # a bitmap with each bit denoting the availability of a particular
+       # control. For example to flag the 0th, 2nd and 3rd controls available:
+       echo 0x0d > bmControls
+
+       # Set the GUID; this is a vendor-specific code identifying the XU.
+       echo -e -n "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" > guidExtensionCode
+
+       popd
+
+The bmControls attribute and the baSourceID attribute are multi-value attributes.
+This means that you may write multiple newline separated values to them. For
+example to flag the 1st, 2nd, 9th and 10th controls as being available you would
+need to write two values to bmControls, like so:
+
+.. code-block:: bash
+
+       cat << EOF > bmControls
+       0x03
+       0x03
+       EOF
+
+The multi-value nature of the baSourceID attribute belies the fact that XUs can
+be multiple-input, though note that this currently has no significant effect.
+
+The bControlSize attribute reflects the size of the bmControls attribute, and
+similarly bNrInPins reflects the size of the baSourceID attributes. Both
+attributes are automatically increased / decreased as you set bmControls and
+baSourceID. It is also possible to manually increase or decrease bControlSize
+which has the effect of truncating entries to the new size, or padding entries
+out with 0x00, for example:
+
+::
+
+       $ cat bmControls
+       0x03
+       0x05
+
+       $ cat bControlSize
+       2
+
+       $ echo 1 > bControlSize
+       $ cat bmControls
+       0x03
+
+       $ echo 2 > bControlSize
+       $ cat bmControls
+       0x03
+       0x00
+
+bNrInPins and baSourceID function in the same way.
+
+Custom Strings Support
+~~~~~~~~~~~~~~~~~~~~~~
+
+String descriptors that provide a textual description for various parts of a
+USB device can be defined in the usual place within USB configfs, and may then
+be linked to from the UVC function root or from Extension Unit directories to
+assign those strings as descriptors:
+
+.. code-block:: bash
+
+       # Create a string descriptor in us-EN and link to it from the function
+       # root. The name of the link is significant here, as it declares this
+       # descriptor to be intended for the Interface Association Descriptor.
+       # Other significant link names at function root are vs0_desc and vs1_desc
+       # For the VideoStreaming Interface 0/1 Descriptors.
+
+       mkdir -p $GADGET/strings/0x409/iad_desc
+       echo -n "Interface Associaton Descriptor" > $GADGET/strings/0x409/iad_desc/s
+       ln -s $GADGET/strings/0x409/iad_desc $FUNCTION/iad_desc
+
+       # Because the link to a String Descriptor from an Extension Unit clearly
+       # associates the two, the name of this link is not significant and may
+       # be set freely.
+
+       mkdir -p $GADGET/strings/0x409/xu.0
+       echo -n "A Very Useful Extension Unit" > $GADGET/strings/0x409/xu.0/s
+       ln -s $GADGET/strings/0x409/xu.0 $FUNCTION/control/extensions/xu.0
+
+The interrupt endpoint
+~~~~~~~~~~~~~~~~~~~~~~
+
+The VideoControl interface has an optional interrupt endpoint which is by default
+disabled. This is intended to support delayed response control set requests for
+UVC (which should respond through the interrupt endpoint rather than tying up
+endpoint 0). At present support for sending data through this endpoint is missing
+and so it is left disabled to avoid confusion. If you wish to enable it you can
+do so through the configfs attribute:
+
+.. code-block:: bash
+
+       echo 1 > $FUNCTION/control/enable_interrupt_ep
+
+Bandwidth configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There are three attributes which control the bandwidth of the USB connection.
+These live in the function root and can be set within limits:
+
+.. code-block:: bash
+
+       # streaming_interval sets bInterval. Values range from 1..255
+       echo 1 > $FUNCTION/streaming_interval
+
+       # streaming_maxpacket sets wMaxPacketSize. Valid values are 1024/2048/3072
+       echo 3072 > $FUNCTION/streaming_maxpacket
+
+       # streaming_maxburst sets bMaxBurst. Valid values are 1..15
+       echo 1 > $FUNCTION/streaming_maxburst
+
+
+The values passed here will be clamped to valid values according to the UVC
+specification (which depend on the speed of the USB connection). To understand
+how the settings influence bandwidth you should consult the UVC specifications,
+but a rule of thumb is that increasing the streaming_maxpacket setting will
+improve bandwidth (and thus the maximum possible framerate), whilst the same is
+true for streaming_maxburst provided the USB connection is running at SuperSpeed.
+Increasing streaming_interval will reduce bandwidth and framerate.
+
+The userspace application
+-------------------------
+By itself, the UVC Gadget driver cannot do anything particularly interesting. It
+must be paired with a userspace program that responds to UVC control requests and
+fills buffers to be queued to the V4L2 device that the driver creates. How those
+things are achieved is implementation dependent and beyond the scope of this
+document, but a reference application can be found at https://gitlab.freedesktop.org/camera/uvc-gadget
index b656c9b..27955da 100644 (file)
@@ -16,6 +16,7 @@ USB support
     gadget_multi
     gadget_printer
     gadget_serial
+    gadget_uvc
     gadget-testing
     iuu_phoenix
     mass-storage
index d8ebab5..1dc8bd2 100644 (file)
@@ -21643,6 +21643,7 @@ USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
 M:     Shuah Khan <shuah@kernel.org>
 M:     Shuah Khan <skhan@linuxfoundation.org>
+R:     Hongren Zheng <i@zenithal.me>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/usbip_protocol.rst
index a2c310d..da2586d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 94944cc..dd03e38 100644 (file)
 
 &usbotg1 {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        srp-disable;
        hnp-disable;
index ace3eb8..4e1bf08 100644 (file)
 
 &usbotg1 {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        srp-disable;
        hnp-disable;
index da13990..815119c 100644 (file)
 
 &usbotg1 {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        srp-disable;
        hnp-disable;
index de2fb1c..b823812 100644 (file)
        };
 
        reserved-memory {
+               sbl_region: sbl@2f00000 {
+                       reg = <0x02f00000 0x100000>;
+                       no-map;
+               };
+
+               external_image_region: external-image@3100000 {
+                       reg = <0x03100000 0x200000>;
+                       no-map;
+               };
+
                adsp_region: adsp@3300000 {
                        reg = <0x03300000 0x1400000>;
                        no-map;
index 14eecaa..e4c2677 100644 (file)
@@ -116,7 +116,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
                        tocopy = n;
 
                ua_flags = uaccess_save_and_enable();
-               memcpy((void *)to, from, tocopy);
+               __memcpy((void *)to, from, tocopy);
                uaccess_restore(ua_flags);
                to += tocopy;
                from += tocopy;
@@ -178,7 +178,7 @@ __clear_user_memset(void __user *addr, unsigned long n)
                        tocopy = n;
 
                ua_flags = uaccess_save_and_enable();
-               memset((void *)addr, 0, tocopy);
+               __memset((void *)addr, 0, tocopy);
                uaccess_restore(ua_flags);
                addr += tocopy;
                n -= tocopy;
index 1023e89..0278921 100644 (file)
@@ -1150,6 +1150,16 @@ config NVIDIA_CARMEL_CNP_ERRATUM
 
          If unsure, say Y.
 
+config ROCKCHIP_ERRATUM_3588001
+       bool "Rockchip 3588001: GIC600 can not support shareability attributes"
+       default y
+       help
+         The Rockchip RK3588 GIC600 SoC integration does not support ACE/ACE-lite.
+         This means, that its sharability feature may not be used, even though it
+         is supported by the IP itself.
+
+         If unsure, say Y.
+
 config SOCIONEXT_SYNQUACER_PREITS
        bool "Socionext Synquacer: Workaround for GICv3 pre-ITS"
        default y
index af9194e..73eb606 100644 (file)
 };
 
 &enetc_port2 {
-       nvmem-cells = <&base_mac_address 2>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
 &enetc_port3 {
-       nvmem-cells = <&base_mac_address 3>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -84,8 +80,6 @@
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy0>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 4>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -94,8 +88,6 @@
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy1>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 5>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy2>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 6>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy3>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 7>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
index 1f34c75..7cd29ab 100644 (file)
@@ -55,7 +55,5 @@
 &enetc_port1 {
        phy-handle = <&phy0>;
        phy-mode = "rgmii-id";
-       nvmem-cells = <&base_mac_address 0>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
index aac4119..113b1df 100644 (file)
 };
 
 &enetc_port2 {
-       nvmem-cells = <&base_mac_address 2>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
 &enetc_port3 {
-       nvmem-cells = <&base_mac_address 3>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -56,8 +52,6 @@
        managed = "in-band-status";
        phy-handle = <&phy0>;
        phy-mode = "sgmii";
-       nvmem-cells = <&base_mac_address 0>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -66,8 +60,6 @@
        managed = "in-band-status";
        phy-handle = <&phy1>;
        phy-mode = "sgmii";
-       nvmem-cells = <&base_mac_address 1>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
index a4421db..9b5e92f 100644 (file)
@@ -43,7 +43,5 @@
 &enetc_port1 {
        phy-handle = <&phy1>;
        phy-mode = "rgmii-id";
-       nvmem-cells = <&base_mac_address 1>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
index 8b65af4..4ab17b9 100644 (file)
@@ -92,8 +92,6 @@
        phy-handle = <&phy0>;
        phy-mode = "sgmii";
        managed = "in-band-status";
-       nvmem-cells = <&base_mac_address 0>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
                                label = "bootloader environment";
                        };
                };
-
-               otp-1 {
-                       compatible = "user-otp";
-
-                       nvmem-layout {
-                               compatible = "kontron,sl28-vpd";
-
-                               serial_number: serial-number {
-                               };
-
-                               base_mac_address: base-mac-address {
-                                       #nvmem-cell-cells = <1>;
-                               };
-                       };
-               };
        };
 };
 
index 1f3d225..06b94bb 100644 (file)
@@ -117,7 +117,7 @@ lsio_subsys: bus@5d000000 {
                interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clk IMX_SC_R_FSPI_0 IMX_SC_PM_CLK_PER>,
                         <&clk IMX_SC_R_FSPI_0 IMX_SC_PM_CLK_PER>;
-               clock-names = "fspi", "fspi_en";
+               clock-names = "fspi_en", "fspi";
                power-domains = <&pd IMX_SC_R_FSPI_0>;
                status = "disabled";
        };
index 1bcf228..8524203 100644 (file)
        phy-handle = <&ethphy0>;
        nvmem-cells = <&fec_mac1>;
        nvmem-cell-names = "mac-address";
-       snps,reset-gpios = <&pca6416_1 2 GPIO_ACTIVE_LOW>;
-       snps,reset-delays-us = <10 20 200000>;
        status = "okay";
 
        mdio {
                        eee-broken-1000t;
                        qca,disable-smarteee;
                        qca,disable-hibernation-mode;
+                       reset-gpios = <&pca6416_1 2 GPIO_ACTIVE_LOW>;
+                       reset-assert-us = <20>;
+                       reset-deassert-us = <200000>;
                        vddio-supply = <&vddio0>;
 
                        vddio0: vddio-regulator {
index 6357078..0e8f0d7 100644 (file)
                compatible = "wlf,wm8960";
                reg = <0x1a>;
                clocks = <&clk IMX8MM_CLK_SAI1_ROOT>;
-               clock-names = "mclk1";
+               clock-names = "mclk";
                wlf,shared-lrclk;
                #sound-dai-cells = <0>;
        };
index ed9ac6c..9e0ddd6 100644 (file)
                                sai2: sai@30020000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30020000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI2_IPG>,
                                                <&clk IMX8MN_CLK_DUMMY>,
                                sai3: sai@30030000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30030000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI3_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
                                sai5: sai@30050000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30050000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI5_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
                                sai6: sai@30060000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30060000  0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI6_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
                                sai7: sai@300b0000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x300b0000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI7_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
index a19224f..2dd60e3 100644 (file)
                                reg = <0x32e90000 0x238>;
                                interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT>,
-                                        <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
-                                        <&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
+                                        <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
+                                        <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
                                assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
                                                  <&clk IMX8MP_VIDEO_PLL1>;
index 2076f9c..41efd97 100644 (file)
                        lpi2c1: i2c@44340000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x44340000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C1_GATE>,
                                         <&clk IMX93_CLK_BUS_AON>;
                        lpi2c2: i2c@44350000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x44350000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C2_GATE>,
                                         <&clk IMX93_CLK_BUS_AON>;
                        lpi2c3: i2c@42530000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x42530000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C3_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c4: i2c@42540000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x42540000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C4_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c5: i2c@426b0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426b0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C5_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c6: i2c@426c0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426c0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C6_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c7: i2c@426d0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426d0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C7_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c8: i2c@426e0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426e0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C8_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        eqos: ethernet@428a0000 {
                                compatible = "nxp,imx93-dwmac-eqos", "snps,dwmac-5.10a";
                                reg = <0x428a0000 0x10000>;
-                               interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>,
-                                            <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
-                               interrupt-names = "eth_wake_irq", "macirq";
+                               interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "macirq", "eth_wake_irq";
                                clocks = <&clk IMX93_CLK_ENET_QOS_GATE>,
                                         <&clk IMX93_CLK_ENET_QOS_GATE>,
                                         <&clk IMX93_CLK_ENET_TIMER2>,
                                                         <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>;
                                assigned-clock-rates = <100000000>, <250000000>;
                                intf_mode = <&wakeupmix_gpr 0x28>;
-                               clk_csr = <0>;
+                               snps,clk-csr = <0>;
                                status = "disabled";
                        };
 
index 133dbe5..7096b99 100644 (file)
@@ -22,7 +22,7 @@
 
                #address-cells = <2>;
                #size-cells = <2>;
-               ranges = <0x0 0x0 0x0 0x0 0x0 0x40000000>;
+               ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
 
                apbmisc: misc@100000 {
                        compatible = "nvidia,tegra194-misc";
index 8fe8eda..f1748cf 100644 (file)
@@ -20,7 +20,7 @@
 
                #address-cells = <2>;
                #size-cells = <2>;
-               ranges = <0x0 0x0 0x0 0x0 0x0 0x40000000>;
+               ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
 
                misc@100000 {
                        compatible = "nvidia,tegra234-misc";
index c492db8..82e2603 100644 (file)
@@ -33,7 +33,3 @@
 &gpio_leds_default {
        pins = "gpio81", "gpio82", "gpio83";
 };
-
-&sim_ctrl_default {
-       pins = "gpio1", "gpio2";
-};
index 700cf81..8433c97 100644 (file)
        gpios = <&msmgpio 20 GPIO_ACTIVE_HIGH>;
 };
 
+&mpss {
+       pinctrl-0 = <&sim_ctrl_default>;
+       pinctrl-names = "default";
+};
+
 &button_default {
        pins = "gpio37";
        bias-pull-down;
        pins = "gpio20", "gpio21", "gpio22";
 };
 
-&sim_ctrl_default {
-       pins = "gpio1", "gpio2";
+/* This selects the external SIM card slot by default */
+&msmgpio {
+       sim_ctrl_default: sim-ctrl-default-state {
+               esim-sel-pins {
+                       pins = "gpio0", "gpio3";
+                       bias-disable;
+                       output-low;
+               };
+
+               sim-en-pins {
+                       pins = "gpio1";
+                       bias-disable;
+                       output-low;
+               };
+
+               sim-sel-pins {
+                       pins = "gpio2";
+                       bias-disable;
+                       output-high;
+               };
+       };
 };
index 790a969..cdf34b7 100644 (file)
@@ -92,9 +92,6 @@
 };
 
 &mpss {
-       pinctrl-0 = <&sim_ctrl_default>;
-       pinctrl-names = "default";
-
        status = "okay";
 };
 
                drive-strength = <2>;
                bias-disable;
        };
-
-       sim_ctrl_default: sim-ctrl-default-state {
-               function = "gpio";
-               drive-strength = <2>;
-               bias-disable;
-               output-low;
-       };
 };
index 3ccb5ff..24fa449 100644 (file)
 };
 
 &remoteproc_nsp0 {
-       firmware-name = "qcom/sa8540p/cdsp.mbn";
+       firmware-name = "qcom/sa8540p/cdsp0.mbn";
        status = "okay";
 };
 
index bdcb749..8f4ab6b 100644 (file)
                        pinctrl-names = "default";
                        pinctrl-0 = <&pcie1_clkreq_n>;
 
+                       dma-coherent;
+
                        iommus = <&apps_smmu 0x1c80 0x1>;
 
                        iommu-map = <0x0 &apps_smmu 0x1c80 0x1>,
index 98e71b9..99c6d65 100644 (file)
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
                        regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+                       regulator-always-on;
                };
 
                vreg_s11b: smps11 {
                        regulator-min-microvolt = <1272000>;
                        regulator-max-microvolt = <1272000>;
                        regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+                       regulator-always-on;
                };
 
                vreg_s12b: smps12 {
                        regulator-min-microvolt = <984000>;
                        regulator-max-microvolt = <984000>;
                        regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+                       regulator-always-on;
                };
 
                vreg_l3b: ldo3 {
                        regulator-min-microvolt = <3008000>;
                        regulator-max-microvolt = <3960000>;
                        regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+                       regulator-always-on;
                };
        };
 
        pmic-die-temp@3 {
                reg = <PMK8350_ADC7_DIE_TEMP>;
                qcom,pre-scaling = <1 1>;
+               label = "pmk8350_die_temp";
        };
 
        xo-therm@44 {
                reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "pmk8350_xo_therm";
        };
 
        pmic-die-temp@103 {
                reg = <PM8350_ADC7_DIE_TEMP(1)>;
                qcom,pre-scaling = <1 1>;
+               label = "pmc8280_1_die_temp";
        };
 
        sys-therm@144 {
                reg = <PM8350_ADC7_AMUX_THM1_100K_PU(1)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm1";
        };
 
        sys-therm@145 {
                reg = <PM8350_ADC7_AMUX_THM2_100K_PU(1)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm2";
        };
 
        sys-therm@146 {
                reg = <PM8350_ADC7_AMUX_THM3_100K_PU(1)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm3";
        };
 
        sys-therm@147 {
                reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm4";
        };
 
        pmic-die-temp@303 {
                reg = <PM8350_ADC7_DIE_TEMP(3)>;
                qcom,pre-scaling = <1 1>;
+               label = "pmc8280_2_die_temp";
        };
 
        sys-therm@344 {
                reg = <PM8350_ADC7_AMUX_THM1_100K_PU(3)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm5";
        };
 
        sys-therm@345 {
                reg = <PM8350_ADC7_AMUX_THM2_100K_PU(3)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm6";
        };
 
        sys-therm@346 {
                reg = <PM8350_ADC7_AMUX_THM3_100K_PU(3)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm7";
        };
 
        sys-therm@347 {
                reg = <PM8350_ADC7_AMUX_THM4_100K_PU(3)>;
                qcom,hw-settle-time = <200>;
                qcom,ratiometric;
+               label = "sys_therm8";
        };
 
        pmic-die-temp@403 {
                reg = <PMR735A_ADC7_DIE_TEMP>;
                qcom,pre-scaling = <1 1>;
+               label = "pmr735a_die_temp";
        };
 };
 
                "VA DMIC0", "MIC BIAS1",
                "VA DMIC1", "MIC BIAS1",
                "VA DMIC2", "MIC BIAS3",
-               "TX DMIC0", "MIC BIAS1",
-               "TX DMIC1", "MIC BIAS2",
-               "TX DMIC2", "MIC BIAS3",
+               "VA DMIC0", "VA MIC BIAS1",
+               "VA DMIC1", "VA MIC BIAS1",
+               "VA DMIC2", "VA MIC BIAS3",
                "TX SWR_ADC1", "ADC2_OUTPUT";
 
        wcd-playback-dai-link {
        va-dai-link {
                link-name = "VA Capture";
                cpu {
-                       sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>;
+                       sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>;
                };
 
                platform {
 
        vdd-micb-supply = <&vreg_s10b>;
 
-       qcom,dmic-sample-rate = <600000>;
+       qcom,dmic-sample-rate = <4800000>;
 
        status = "okay";
 };
index 0d02599..42bfa9f 100644 (file)
                        qcom,ports-sinterval-low =      /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>;
                        qcom,ports-offset1 =            /bits/ 8 <0x00 0x00 0x0B 0x01 0x00>;
                        qcom,ports-offset2 =            /bits/ 8 <0x00 0x00 0x0B 0x00 0x00>;
-                       qcom,ports-hstart =             /bits/ 8 <0xff 0x03 0xff 0xff 0xff>;
-                       qcom,ports-hstop =              /bits/ 8 <0xff 0x06 0xff 0xff 0xff>;
+                       qcom,ports-hstart =             /bits/ 8 <0xff 0x03 0x00 0xff 0xff>;
+                       qcom,ports-hstop =              /bits/ 8 <0xff 0x06 0x0f 0xff 0xff>;
                        qcom,ports-word-length =        /bits/ 8 <0x01 0x07 0x04 0xff 0xff>;
-                       qcom,ports-block-pack-mode =    /bits/ 8 <0xff 0x00 0x01 0xff 0xff>;
+                       qcom,ports-block-pack-mode =    /bits/ 8 <0xff 0xff 0x01 0xff 0xff>;
                        qcom,ports-lane-control =       /bits/ 8 <0x01 0x00 0x00 0x00 0x00>;
-                       qcom,ports-block-group-count =  /bits/ 8 <0xff 0xff 0xff 0xff 0x00>;
+                       qcom,ports-block-group-count =  /bits/ 8 <0xff 0xff 0xff 0xff 0xff>;
 
                        #sound-dai-cells = <1>;
                        #address-cells = <2>;
                                              <&intc GIC_SPI 520 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "core", "wake";
 
-                       clocks = <&vamacro>;
+                       clocks = <&txmacro>;
                        clock-names = "iface";
                        label = "TX";
                        #sound-dai-cells = <1>;
 
                        qcom,din-ports = <4>;
                        qcom,dout-ports = <0>;
-                       qcom,ports-sinterval-low =      /bits/ 8 <0x01 0x03 0x03 0x03>;
-                       qcom,ports-offset1 =            /bits/ 8 <0x01 0x00 0x02 0x01>;
+                       qcom,ports-sinterval-low =      /bits/ 8 <0x01 0x01 0x03 0x03>;
+                       qcom,ports-offset1 =            /bits/ 8 <0x01 0x00 0x02 0x00>;
                        qcom,ports-offset2 =            /bits/ 8 <0x00 0x00 0x00 0x00>;
                        qcom,ports-block-pack-mode =    /bits/ 8 <0xff 0xff 0xff 0xff>;
                        qcom,ports-hstart =             /bits/ 8 <0xff 0xff 0xff 0xff>;
                        qcom,ports-hstop =              /bits/ 8 <0xff 0xff 0xff 0xff>;
-                       qcom,ports-word-length =        /bits/ 8 <0xff 0x00 0xff 0xff>;
+                       qcom,ports-word-length =        /bits/ 8 <0xff 0xff 0xff 0xff>;
                        qcom,ports-block-group-count =  /bits/ 8 <0xff 0xff 0xff 0xff>;
-                       qcom,ports-lane-control =       /bits/ 8 <0x00 0x01 0x00 0x00>;
+                       qcom,ports-lane-control =       /bits/ 8 <0x00 0x01 0x00 0x01>;
 
                        status = "disabled";
                };
index 4d6ec81..fbd67d2 100644 (file)
                                dma-names = "tx", "rx";
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               status = "disabled";
                        };
                };
 
index 31b88c7..068ee4f 100644 (file)
                        clock-names = "xo";
 
                        power-domains = <&rpmpd SM6375_VDDCX>;
+                       power-domain-names = "cx";
 
                        memory-region = <&pil_cdsp_mem>;
 
index fd20096..13e0ce8 100644 (file)
                                      "slave_q2a",
                                      "tbu";
 
-                       iommus = <&apps_smmu 0x1d80 0x7f>;
+                       iommus = <&apps_smmu 0x1d80 0x3f>;
                        iommu-map = <0x0   &apps_smmu 0x1d80 0x1>,
                                    <0x100 &apps_smmu 0x1d81 0x1>;
 
                        assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>;
                        assigned-clock-rates = <19200000>;
 
-                       iommus = <&apps_smmu 0x1e00 0x7f>;
+                       iommus = <&apps_smmu 0x1e00 0x3f>;
                        iommu-map = <0x0   &apps_smmu 0x1e00 0x1>,
                                    <0x100 &apps_smmu 0x1e01 0x1>;
 
index acaa99c..a85d47f 100644 (file)
 };
 
 &venus {
-       firmware-name = "qcom/sm8250/elish/venus.mbn";
+       firmware-name = "qcom/sm8250/xiaomi/elish/venus.mbn";
        status = "okay";
 };
index 1c97e28..1a5a612 100644 (file)
                        power-domains = <&gcc UFS_PHY_GDSC>;
 
                        iommus = <&apps_smmu 0xe0 0x0>;
+                       dma-coherent;
 
                        clock-names =
                                "core_clk",
index 1a744a3..b285b15 100644 (file)
                                 <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
                                 <&vamacro>;
                        clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
-                       assigned-clocks = <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
-                                         <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+                       assigned-clocks = <&q6prmcc LPASS_CLK_ID_WSA2_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+                                         <&q6prmcc LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
                        assigned-clock-rates = <19200000>, <19200000>;
 
                        #clock-cells = <0>;
                        power-domains = <&gcc UFS_PHY_GDSC>;
 
                        iommus = <&apps_smmu 0xe0 0x0>;
+                       dma-coherent;
 
                        interconnects = <&aggre1_noc MASTER_UFS_MEM 0 &mc_virt SLAVE_EBI1 0>,
                                        <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_UFS_MEM_CFG 0>;
index ff4d342..5d08883 100644 (file)
@@ -66,7 +66,7 @@
 
                CPU0: cpu@0 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a510";
                        reg = <0 0>;
                        enable-method = "psci";
                        next-level-cache = <&L2_0>;
@@ -89,7 +89,7 @@
 
                CPU1: cpu@100 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a510";
                        reg = <0 0x100>;
                        enable-method = "psci";
                        next-level-cache = <&L2_100>;
 
                CPU2: cpu@200 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a510";
                        reg = <0 0x200>;
                        enable-method = "psci";
                        next-level-cache = <&L2_200>;
 
                CPU3: cpu@300 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a715";
                        reg = <0 0x300>;
                        enable-method = "psci";
                        next-level-cache = <&L2_300>;
 
                CPU4: cpu@400 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a715";
                        reg = <0 0x400>;
                        enable-method = "psci";
                        next-level-cache = <&L2_400>;
 
                CPU5: cpu@500 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a710";
                        reg = <0 0x500>;
                        enable-method = "psci";
                        next-level-cache = <&L2_500>;
 
                CPU6: cpu@600 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-a710";
                        reg = <0 0x600>;
                        enable-method = "psci";
                        next-level-cache = <&L2_600>;
 
                CPU7: cpu@700 {
                        device_type = "cpu";
-                       compatible = "qcom,kryo";
+                       compatible = "arm,cortex-x3";
                        reg = <0 0x700>;
                        enable-method = "psci";
                        next-level-cache = <&L2_700>;
                        required-opps = <&rpmhpd_opp_nom>;
 
                        iommus = <&apps_smmu 0x60 0x0>;
+                       dma-coherent;
 
                        interconnects = <&aggre1_noc MASTER_UFS_MEM 0 &mc_virt SLAVE_EBI1 0>,
                                        <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_UFS_MEM_CFG 0>;
                lpass_tlmm: pinctrl@6e80000 {
                        compatible = "qcom,sm8550-lpass-lpi-pinctrl";
                        reg = <0 0x06e80000 0 0x20000>,
-                             <0 0x0725a000 0 0x10000>;
+                             <0 0x07250000 0 0x10000>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-ranges = <&lpass_tlmm 0 0 23>;
                                pins = "gpio28", "gpio29";
                                function = "qup1_se0";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c1_data_clk: qup-i2c1-data-clk-state {
                                pins = "gpio32", "gpio33";
                                function = "qup1_se1";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c2_data_clk: qup-i2c2-data-clk-state {
                                pins = "gpio36", "gpio37";
                                function = "qup1_se2";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c3_data_clk: qup-i2c3-data-clk-state {
                                pins = "gpio40", "gpio41";
                                function = "qup1_se3";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c4_data_clk: qup-i2c4-data-clk-state {
                                pins = "gpio44", "gpio45";
                                function = "qup1_se4";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c5_data_clk: qup-i2c5-data-clk-state {
                                pins = "gpio52", "gpio53";
                                function = "qup1_se5";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c6_data_clk: qup-i2c6-data-clk-state {
                                pins = "gpio48", "gpio49";
                                function = "qup1_se6";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c8_data_clk: qup-i2c8-data-clk-state {
                                        pins = "gpio57";
                                        function = "qup2_se0_l1_mira";
                                        drive-strength = <2>;
-                                       bias-pull-up;
+                                       bias-pull-up = <2200>;
                                };
 
                                sda-pins {
                                        pins = "gpio56";
                                        function = "qup2_se0_l0_mira";
                                        drive-strength = <2>;
-                                       bias-pull-up;
+                                       bias-pull-up = <2200>;
                                };
                        };
 
                                pins = "gpio60", "gpio61";
                                function = "qup2_se1";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c10_data_clk: qup-i2c10-data-clk-state {
                                pins = "gpio64", "gpio65";
                                function = "qup2_se2";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c11_data_clk: qup-i2c11-data-clk-state {
                                pins = "gpio68", "gpio69";
                                function = "qup2_se3";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c12_data_clk: qup-i2c12-data-clk-state {
                                pins = "gpio2", "gpio3";
                                function = "qup2_se4";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c13_data_clk: qup-i2c13-data-clk-state {
                                pins = "gpio80", "gpio81";
                                function = "qup2_se5";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_i2c15_data_clk: qup-i2c15-data-clk-state {
                                pins = "gpio72", "gpio106";
                                function = "qup2_se7";
                                drive-strength = <2>;
-                               bias-pull-up;
+                               bias-pull-up = <2200>;
                        };
 
                        qup_spi0_cs: qup-spi0-cs-state {
index 28d8a5d..d731b46 100644 (file)
@@ -66,7 +66,7 @@
        .long   .Lefi_header_end - .L_head              // SizeOfHeaders
        .long   0                                       // CheckSum
        .short  IMAGE_SUBSYSTEM_EFI_APPLICATION         // Subsystem
-       .short  0                                       // DllCharacteristics
+       .short  IMAGE_DLL_CHARACTERISTICS_NX_COMPAT     // DllCharacteristics
        .quad   0                                       // SizeOfStackReserve
        .quad   0                                       // SizeOfStackCommit
        .quad   0                                       // SizeOfHeapReserve
index 92a9682..365d272 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef __ASM_KASAN_H
 #define __ASM_KASAN_H
 
-#ifdef CONFIG_KASAN
+#if defined(CONFIG_KASAN) && !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX)
 #define _GLOBAL_KASAN(fn)      _GLOBAL(__##fn)
 #define _GLOBAL_TOC_KASAN(fn)  _GLOBAL_TOC(__##fn)
 #define EXPORT_SYMBOL_KASAN(fn)        EXPORT_SYMBOL(__##fn)
index 2aa0e31..60ba227 100644 (file)
@@ -30,11 +30,17 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
 extern void * memchr(const void *,int,__kernel_size_t);
 void memcpy_flushcache(void *dest, const void *src, size_t size);
 
+#ifdef CONFIG_KASAN
+/* __mem variants are used by KASAN to implement instrumented meminstrinsics. */
+#ifdef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
+#define __memset memset
+#define __memcpy memcpy
+#define __memmove memmove
+#else /* CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */
 void *__memset(void *s, int c, __kernel_size_t count);
 void *__memcpy(void *to, const void *from, __kernel_size_t n);
 void *__memmove(void *to, const void *from, __kernel_size_t n);
-
-#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
+#ifndef __SANITIZE_ADDRESS__
 /*
  * For files that are not instrumented (e.g. mm/slub.c) we
  * should use not instrumented version of mem* functions.
@@ -46,8 +52,9 @@ void *__memmove(void *to, const void *from, __kernel_size_t n);
 #ifndef __NO_FORTIFY
 #define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
 #endif
-
-#endif
+#endif /* !__SANITIZE_ADDRESS__ */
+#endif /* CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */
+#endif /* CONFIG_KASAN */
 
 #ifdef CONFIG_PPC64
 #ifndef CONFIG_KASAN
index 5a31986..69623b9 100644 (file)
 # If you really need to reference something from prom_init.o add
 # it to the list below:
 
-grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
-if [ $? -eq 0 ]
+has_renamed_memintrinsics()
+{
+       grep -q "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} && \
+               ! grep -q "^CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y" ${KCONFIG_CONFIG}
+}
+
+if has_renamed_memintrinsics
 then
        MEM_FUNCS="__memcpy __memset"
 else
index c5e42cc..b90be75 100644 (file)
@@ -63,6 +63,8 @@ config RISCV
        select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
        select GENERIC_IDLE_POLL_SETUP
        select GENERIC_IOREMAP if MMU
+       select GENERIC_IRQ_IPI if SMP
+       select GENERIC_IRQ_IPI_MUX if SMP
        select GENERIC_IRQ_MULTI_HANDLER
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_SHOW_LEVEL
@@ -464,6 +466,28 @@ config TOOLCHAIN_HAS_ZIHINTPAUSE
        depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zihintpause)
        depends on LLD_VERSION >= 150000 || LD_VERSION >= 23600
 
+config TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
+       def_bool y
+       # https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aed44286efa8ae8717a77d94b51ac3614e2ca6dc
+       depends on AS_IS_GNU && AS_VERSION >= 23800
+       help
+         Newer binutils versions default to ISA spec version 20191213 which
+         moves some instructions from the I extension to the Zicsr and Zifencei
+         extensions.
+
+config TOOLCHAIN_NEEDS_OLD_ISA_SPEC
+       def_bool y
+       depends on TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
+       # https://github.com/llvm/llvm-project/commit/22e199e6afb1263c943c0c0d4498694e15bf8a16
+       depends on CC_IS_CLANG && CLANG_VERSION < 170000
+       help
+         Certain versions of clang do not support zicsr and zifencei via -march
+         but newer versions of binutils require it for the reasons noted in the
+         help text of CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI. This
+         option causes an older ISA spec compatible with these older versions
+         of clang to be passed to GAS, which has the same result as passing zicsr
+         and zifencei to -march.
+
 config FPU
        bool "FPU support"
        default y
index 4de83b9..b05e833 100644 (file)
@@ -57,10 +57,12 @@ riscv-march-$(CONFIG_ARCH_RV64I)    := rv64ima
 riscv-march-$(CONFIG_FPU)              := $(riscv-march-y)fd
 riscv-march-$(CONFIG_RISCV_ISA_C)      := $(riscv-march-y)c
 
-# Newer binutils versions default to ISA spec version 20191213 which moves some
-# instructions from the I extension to the Zicsr and Zifencei extensions.
-toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
-riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
+ifdef CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC
+KBUILD_CFLAGS += -Wa,-misa-spec=2.2
+KBUILD_AFLAGS += -Wa,-misa-spec=2.2
+else
+riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei
+endif
 
 # Check if the toolchain supports Zihintpause extension
 riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE) := $(riscv-march-y)_zihintpause
index e4c4355..43b9ebf 100644 (file)
 
 #include <asm-generic/irq.h>
 
+void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
+
+struct fwnode_handle *riscv_get_intc_hwnode(void);
+
 extern void __init init_IRQ(void);
 
 #endif /* _ASM_RISCV_IRQ_H */
index 945b7be..acab441 100644 (file)
@@ -271,8 +271,7 @@ long sbi_get_marchid(void);
 long sbi_get_mimpid(void);
 void sbi_set_timer(uint64_t stime_value);
 void sbi_shutdown(void);
-void sbi_clear_ipi(void);
-int sbi_send_ipi(const struct cpumask *cpu_mask);
+void sbi_send_ipi(unsigned int cpu);
 int sbi_remote_fence_i(const struct cpumask *cpu_mask);
 int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
                           unsigned long start,
@@ -335,4 +334,10 @@ unsigned long riscv_cached_mvendorid(unsigned int cpu_id);
 unsigned long riscv_cached_marchid(unsigned int cpu_id);
 unsigned long riscv_cached_mimpid(unsigned int cpu_id);
 
+#if IS_ENABLED(CONFIG_SMP) && IS_ENABLED(CONFIG_RISCV_SBI)
+void sbi_ipi_init(void);
+#else
+static inline void sbi_ipi_init(void) { }
+#endif
+
 #endif /* _ASM_RISCV_SBI_H */
index 3831b63..c4b7701 100644 (file)
 struct seq_file;
 extern unsigned long boot_cpu_hartid;
 
-struct riscv_ipi_ops {
-       void (*ipi_inject)(const struct cpumask *target);
-       void (*ipi_clear)(void);
-};
-
 #ifdef CONFIG_SMP
+
+#include <linux/jump_label.h>
+
 /*
  * Mapping between linux logical cpu index and hartid.
  */
@@ -33,9 +31,6 @@ void show_ipi_stats(struct seq_file *p, int prec);
 /* SMP initialization hook for setup_arch */
 void __init setup_smp(void);
 
-/* Called from C code, this handles an IPI. */
-void handle_IPI(struct pt_regs *regs);
-
 /* Hook for the generic smp_call_function_many() routine. */
 void arch_send_call_function_ipi_mask(struct cpumask *mask);
 
@@ -44,11 +39,22 @@ void arch_send_call_function_single_ipi(int cpu);
 
 int riscv_hartid_to_cpuid(unsigned long hartid);
 
-/* Set custom IPI operations */
-void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);
+/* Enable IPI for CPU hotplug */
+void riscv_ipi_enable(void);
+
+/* Disable IPI for CPU hotplug */
+void riscv_ipi_disable(void);
 
-/* Clear IPI for current CPU */
-void riscv_clear_ipi(void);
+/* Check if IPI interrupt numbers are available */
+bool riscv_ipi_have_virq_range(void);
+
+/* Set the IPI interrupt numbers for arch (called by irqchip drivers) */
+void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence);
+
+/* Check if we can use IPIs for remote FENCEs */
+DECLARE_STATIC_KEY_FALSE(riscv_ipi_for_rfence);
+#define riscv_use_ipi_for_rfence() \
+       static_branch_unlikely(&riscv_ipi_for_rfence)
 
 /* Check other CPUs stop or not */
 bool smp_crash_stop_failed(void);
@@ -85,14 +91,29 @@ static inline unsigned long cpuid_to_hartid_map(int cpu)
        return boot_cpu_hartid;
 }
 
-static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
+static inline void riscv_ipi_enable(void)
+{
+}
+
+static inline void riscv_ipi_disable(void)
 {
 }
 
-static inline void riscv_clear_ipi(void)
+static inline bool riscv_ipi_have_virq_range(void)
+{
+       return false;
+}
+
+static inline void riscv_ipi_set_virq_range(int virq, int nr,
+                                           bool use_for_rfence)
 {
 }
 
+static inline bool riscv_use_ipi_for_rfence(void)
+{
+       return false;
+}
+
 #endif /* CONFIG_SMP */
 
 #if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP)
index 8010193..a09196f 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/errata_list.h>
 
 #ifdef CONFIG_MMU
+extern unsigned long asid_mask;
+
 static inline void local_flush_tlb_all(void)
 {
        __asm__ __volatile__ ("sfence.vma" : : : "memory");
index 4cf303a..67f542b 100644 (file)
@@ -74,6 +74,7 @@ obj-$(CONFIG_PERF_EVENTS)     += perf_callchain.o
 obj-$(CONFIG_HAVE_PERF_REGS)   += perf_regs.o
 obj-$(CONFIG_RISCV_SBI)                += sbi.o
 ifeq ($(CONFIG_RISCV_SBI), y)
+obj-$(CONFIG_SMP)              += sbi-ipi.o
 obj-$(CONFIG_SMP) += cpu_ops_sbi.o
 endif
 obj-$(CONFIG_HOTPLUG_CPU)      += cpu-hotplug.o
index f7a832e..39235cf 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/irq.h>
 #include <asm/cpu_ops.h>
 #include <asm/numa.h>
-#include <asm/sbi.h>
+#include <asm/smp.h>
 
 bool cpu_has_hotplug(unsigned int cpu)
 {
@@ -43,6 +43,7 @@ int __cpu_disable(void)
        remove_cpu_topology(cpu);
        numa_remove_cpu(cpu);
        set_cpu_online(cpu, false);
+       riscv_ipi_disable();
        irq_migrate_all_off_this_cpu();
 
        return ret;
index 7207fa0..eb9a68a 100644 (file)
@@ -7,8 +7,26 @@
 
 #include <linux/interrupt.h>
 #include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
-#include <asm/smp.h>
+#include <asm/sbi.h>
+
+static struct fwnode_handle *(*__get_intc_node)(void);
+
+void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void))
+{
+       __get_intc_node = fn;
+}
+
+struct fwnode_handle *riscv_get_intc_hwnode(void)
+{
+       if (__get_intc_node)
+               return __get_intc_node();
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode);
 
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
@@ -21,4 +39,5 @@ void __init init_IRQ(void)
        irqchip_init();
        if (!handle_arch_irq)
                panic("No interrupt controller found.");
+       sbi_ipi_init();
 }
diff --git a/arch/riscv/kernel/sbi-ipi.c b/arch/riscv/kernel/sbi-ipi.c
new file mode 100644 (file)
index 0000000..a455969
--- /dev/null
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Multiplex several IPIs over a single HW IPI.
+ *
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ */
+
+#define pr_fmt(fmt) "riscv: " fmt
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <asm/sbi.h>
+
+static int sbi_ipi_virq;
+
+static void sbi_ipi_handle(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(chip, desc);
+
+       csr_clear(CSR_IP, IE_SIE);
+       ipi_mux_process();
+
+       chained_irq_exit(chip, desc);
+}
+
+static int sbi_ipi_starting_cpu(unsigned int cpu)
+{
+       enable_percpu_irq(sbi_ipi_virq, irq_get_trigger_type(sbi_ipi_virq));
+       return 0;
+}
+
+void __init sbi_ipi_init(void)
+{
+       int virq;
+       struct irq_domain *domain;
+
+       if (riscv_ipi_have_virq_range())
+               return;
+
+       domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(),
+                                         DOMAIN_BUS_ANY);
+       if (!domain) {
+               pr_err("unable to find INTC IRQ domain\n");
+               return;
+       }
+
+       sbi_ipi_virq = irq_create_mapping(domain, RV_IRQ_SOFT);
+       if (!sbi_ipi_virq) {
+               pr_err("unable to create INTC IRQ mapping\n");
+               return;
+       }
+
+       virq = ipi_mux_create(BITS_PER_BYTE, sbi_send_ipi);
+       if (virq <= 0) {
+               pr_err("unable to create muxed IPIs\n");
+               irq_dispose_mapping(sbi_ipi_virq);
+               return;
+       }
+
+       irq_set_chained_handler(sbi_ipi_virq, sbi_ipi_handle);
+
+       /*
+        * Don't disable IPI when CPU goes offline because
+        * the masking/unmasking of virtual IPIs is done
+        * via generic IPI-Mux
+        */
+       cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+                         "irqchip/sbi-ipi:starting",
+                         sbi_ipi_starting_cpu, NULL);
+
+       riscv_ipi_set_virq_range(virq, BITS_PER_BYTE, false);
+       pr_info("providing IPIs using SBI IPI extension\n");
+}
index 5c87db8..92b9b75 100644 (file)
@@ -17,7 +17,7 @@ unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
 EXPORT_SYMBOL(sbi_spec_version);
 
 static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
-static int (*__sbi_send_ipi)(const struct cpumask *cpu_mask) __ro_after_init;
+static void (*__sbi_send_ipi)(unsigned int cpu) __ro_after_init;
 static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
                           unsigned long start, unsigned long size,
                           unsigned long arg4, unsigned long arg5) __ro_after_init;
@@ -131,17 +131,6 @@ void sbi_shutdown(void)
 EXPORT_SYMBOL(sbi_shutdown);
 
 /**
- * sbi_clear_ipi() - Clear any pending IPIs for the calling hart.
- *
- * Return: None
- */
-void sbi_clear_ipi(void)
-{
-       sbi_ecall(SBI_EXT_0_1_CLEAR_IPI, 0, 0, 0, 0, 0, 0, 0);
-}
-EXPORT_SYMBOL(sbi_clear_ipi);
-
-/**
  * __sbi_set_timer_v01() - Program the timer for next timer event.
  * @stime_value: The value after which next timer event should fire.
  *
@@ -157,17 +146,12 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
 #endif
 }
 
-static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
+static void __sbi_send_ipi_v01(unsigned int cpu)
 {
-       unsigned long hart_mask;
-
-       if (!cpu_mask || cpumask_empty(cpu_mask))
-               cpu_mask = cpu_online_mask;
-       hart_mask = __sbi_v01_cpumask_to_hartmask(cpu_mask);
-
+       unsigned long hart_mask =
+               __sbi_v01_cpumask_to_hartmask(cpumask_of(cpu));
        sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)(&hart_mask),
                  0, 0, 0, 0, 0);
-       return 0;
 }
 
 static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
@@ -216,12 +200,10 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
                sbi_major_version(), sbi_minor_version());
 }
 
-static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
+static void __sbi_send_ipi_v01(unsigned int cpu)
 {
        pr_warn("IPI extension is not available in SBI v%lu.%lu\n",
                sbi_major_version(), sbi_minor_version());
-
-       return 0;
 }
 
 static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
@@ -248,55 +230,18 @@ static void __sbi_set_timer_v02(uint64_t stime_value)
 #endif
 }
 
-static int __sbi_send_ipi_v02(const struct cpumask *cpu_mask)
+static void __sbi_send_ipi_v02(unsigned int cpu)
 {
-       unsigned long hartid, cpuid, hmask = 0, hbase = 0, htop = 0;
-       struct sbiret ret = {0};
        int result;
+       struct sbiret ret = {0};
 
-       if (!cpu_mask || cpumask_empty(cpu_mask))
-               cpu_mask = cpu_online_mask;
-
-       for_each_cpu(cpuid, cpu_mask) {
-               hartid = cpuid_to_hartid_map(cpuid);
-               if (hmask) {
-                       if (hartid + BITS_PER_LONG <= htop ||
-                           hbase + BITS_PER_LONG <= hartid) {
-                               ret = sbi_ecall(SBI_EXT_IPI,
-                                               SBI_EXT_IPI_SEND_IPI, hmask,
-                                               hbase, 0, 0, 0, 0);
-                               if (ret.error)
-                                       goto ecall_failed;
-                               hmask = 0;
-                       } else if (hartid < hbase) {
-                               /* shift the mask to fit lower hartid */
-                               hmask <<= hbase - hartid;
-                               hbase = hartid;
-                       }
-               }
-               if (!hmask) {
-                       hbase = hartid;
-                       htop = hartid;
-               } else if (hartid > htop) {
-                       htop = hartid;
-               }
-               hmask |= BIT(hartid - hbase);
-       }
-
-       if (hmask) {
-               ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
-                               hmask, hbase, 0, 0, 0, 0);
-               if (ret.error)
-                       goto ecall_failed;
+       ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
+                       1UL, cpuid_to_hartid_map(cpu), 0, 0, 0, 0);
+       if (ret.error) {
+               result = sbi_err_map_linux_errno(ret.error);
+               pr_err("%s: hbase = [%lu] failed (error [%d])\n",
+                       __func__, cpuid_to_hartid_map(cpu), result);
        }
-
-       return 0;
-
-ecall_failed:
-       result = sbi_err_map_linux_errno(ret.error);
-       pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n",
-              __func__, hbase, hmask, result);
-       return result;
 }
 
 static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask,
@@ -410,13 +355,11 @@ void sbi_set_timer(uint64_t stime_value)
 
 /**
  * sbi_send_ipi() - Send an IPI to any hart.
- * @cpu_mask: A cpu mask containing all the target harts.
- *
- * Return: 0 on success, appropriate linux error code otherwise.
+ * @cpu: Logical id of the target CPU.
  */
-int sbi_send_ipi(const struct cpumask *cpu_mask)
+void sbi_send_ipi(unsigned int cpu)
 {
-       return __sbi_send_ipi(cpu_mask);
+       __sbi_send_ipi(cpu);
 }
 EXPORT_SYMBOL(sbi_send_ipi);
 
@@ -641,15 +584,6 @@ long sbi_get_mimpid(void)
 }
 EXPORT_SYMBOL_GPL(sbi_get_mimpid);
 
-static void sbi_send_cpumask_ipi(const struct cpumask *target)
-{
-       sbi_send_ipi(target);
-}
-
-static const struct riscv_ipi_ops sbi_ipi_ops = {
-       .ipi_inject = sbi_send_cpumask_ipi
-};
-
 void __init sbi_init(void)
 {
        int ret;
@@ -696,6 +630,4 @@ void __init sbi_init(void)
                __sbi_send_ipi  = __sbi_send_ipi_v01;
                __sbi_rfence    = __sbi_rfence_v01;
        }
-
-       riscv_set_ipi_ops(&sbi_ipi_ops);
 }
index 8c3b59f..5f985a1 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 #include <linux/irq_work.h>
 
-#include <asm/sbi.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu_ops.h>
@@ -44,11 +45,10 @@ void __init smp_setup_processor_id(void)
        cpuid_to_hartid_map(0) = boot_cpu_hartid;
 }
 
-/* A collection of single bit ipi messages.  */
-static struct {
-       unsigned long stats[IPI_MAX] ____cacheline_aligned;
-       unsigned long bits ____cacheline_aligned;
-} ipi_data[NR_CPUS] __cacheline_aligned;
+static DEFINE_PER_CPU_READ_MOSTLY(int, ipi_dummy_dev);
+static int ipi_virq_base __ro_after_init;
+static int nr_ipi __ro_after_init = IPI_MAX;
+static struct irq_desc *ipi_desc[IPI_MAX] __read_mostly;
 
 int riscv_hartid_to_cpuid(unsigned long hartid)
 {
@@ -100,48 +100,14 @@ static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
 }
 #endif
 
-static const struct riscv_ipi_ops *ipi_ops __ro_after_init;
-
-void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
-{
-       ipi_ops = ops;
-}
-EXPORT_SYMBOL_GPL(riscv_set_ipi_ops);
-
-void riscv_clear_ipi(void)
-{
-       if (ipi_ops && ipi_ops->ipi_clear)
-               ipi_ops->ipi_clear();
-
-       csr_clear(CSR_IP, IE_SIE);
-}
-EXPORT_SYMBOL_GPL(riscv_clear_ipi);
-
 static void send_ipi_mask(const struct cpumask *mask, enum ipi_message_type op)
 {
-       int cpu;
-
-       smp_mb__before_atomic();
-       for_each_cpu(cpu, mask)
-               set_bit(op, &ipi_data[cpu].bits);
-       smp_mb__after_atomic();
-
-       if (ipi_ops && ipi_ops->ipi_inject)
-               ipi_ops->ipi_inject(mask);
-       else
-               pr_warn("SMP: IPI inject method not available\n");
+       __ipi_send_mask(ipi_desc[op], mask);
 }
 
 static void send_ipi_single(int cpu, enum ipi_message_type op)
 {
-       smp_mb__before_atomic();
-       set_bit(op, &ipi_data[cpu].bits);
-       smp_mb__after_atomic();
-
-       if (ipi_ops && ipi_ops->ipi_inject)
-               ipi_ops->ipi_inject(cpumask_of(cpu));
-       else
-               pr_warn("SMP: IPI inject method not available\n");
+       __ipi_send_mask(ipi_desc[op], cpumask_of(cpu));
 }
 
 #ifdef CONFIG_IRQ_WORK
@@ -151,59 +117,98 @@ void arch_irq_work_raise(void)
 }
 #endif
 
-void handle_IPI(struct pt_regs *regs)
+static irqreturn_t handle_IPI(int irq, void *data)
 {
-       unsigned int cpu = smp_processor_id();
-       unsigned long *pending_ipis = &ipi_data[cpu].bits;
-       unsigned long *stats = ipi_data[cpu].stats;
+       int ipi = irq - ipi_virq_base;
+
+       switch (ipi) {
+       case IPI_RESCHEDULE:
+               scheduler_ipi();
+               break;
+       case IPI_CALL_FUNC:
+               generic_smp_call_function_interrupt();
+               break;
+       case IPI_CPU_STOP:
+               ipi_stop();
+               break;
+       case IPI_CPU_CRASH_STOP:
+               ipi_cpu_crash_stop(smp_processor_id(), get_irq_regs());
+               break;
+       case IPI_IRQ_WORK:
+               irq_work_run();
+               break;
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+       case IPI_TIMER:
+               tick_receive_broadcast();
+               break;
+#endif
+       default:
+               pr_warn("CPU%d: unhandled IPI%d\n", smp_processor_id(), ipi);
+               break;
+       }
 
-       riscv_clear_ipi();
+       return IRQ_HANDLED;
+}
 
-       while (true) {
-               unsigned long ops;
+void riscv_ipi_enable(void)
+{
+       int i;
 
-               /* Order bit clearing and data access. */
-               mb();
+       if (WARN_ON_ONCE(!ipi_virq_base))
+               return;
 
-               ops = xchg(pending_ipis, 0);
-               if (ops == 0)
-                       return;
+       for (i = 0; i < nr_ipi; i++)
+               enable_percpu_irq(ipi_virq_base + i, 0);
+}
 
-               if (ops & (1 << IPI_RESCHEDULE)) {
-                       stats[IPI_RESCHEDULE]++;
-                       scheduler_ipi();
-               }
+void riscv_ipi_disable(void)
+{
+       int i;
 
-               if (ops & (1 << IPI_CALL_FUNC)) {
-                       stats[IPI_CALL_FUNC]++;
-                       generic_smp_call_function_interrupt();
-               }
+       if (WARN_ON_ONCE(!ipi_virq_base))
+               return;
 
-               if (ops & (1 << IPI_CPU_STOP)) {
-                       stats[IPI_CPU_STOP]++;
-                       ipi_stop();
-               }
+       for (i = 0; i < nr_ipi; i++)
+               disable_percpu_irq(ipi_virq_base + i);
+}
 
-               if (ops & (1 << IPI_CPU_CRASH_STOP)) {
-                       ipi_cpu_crash_stop(cpu, get_irq_regs());
-               }
+bool riscv_ipi_have_virq_range(void)
+{
+       return (ipi_virq_base) ? true : false;
+}
 
-               if (ops & (1 << IPI_IRQ_WORK)) {
-                       stats[IPI_IRQ_WORK]++;
-                       irq_work_run();
-               }
+DEFINE_STATIC_KEY_FALSE(riscv_ipi_for_rfence);
+EXPORT_SYMBOL_GPL(riscv_ipi_for_rfence);
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-               if (ops & (1 << IPI_TIMER)) {
-                       stats[IPI_TIMER]++;
-                       tick_receive_broadcast();
-               }
-#endif
-               BUG_ON((ops >> IPI_MAX) != 0);
+void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence)
+{
+       int i, err;
+
+       if (WARN_ON(ipi_virq_base))
+               return;
+
+       WARN_ON(nr < IPI_MAX);
+       nr_ipi = min(nr, IPI_MAX);
+       ipi_virq_base = virq;
 
-               /* Order data access and bit testing. */
-               mb();
+       /* Request IPIs */
+       for (i = 0; i < nr_ipi; i++) {
+               err = request_percpu_irq(ipi_virq_base + i, handle_IPI,
+                                        "IPI", &ipi_dummy_dev);
+               WARN_ON(err);
+
+               ipi_desc[i] = irq_to_desc(ipi_virq_base + i);
+               irq_set_status_flags(ipi_virq_base + i, IRQ_HIDDEN);
        }
+
+       /* Enabled IPIs for boot CPU immediately */
+       riscv_ipi_enable();
+
+       /* Update RFENCE static key */
+       if (use_for_rfence)
+               static_branch_enable(&riscv_ipi_for_rfence);
+       else
+               static_branch_disable(&riscv_ipi_for_rfence);
 }
 
 static const char * const ipi_names[] = {
@@ -223,7 +228,7 @@ void show_ipi_stats(struct seq_file *p, int prec)
                seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
                           prec >= 4 ? " " : "");
                for_each_online_cpu(cpu)
-                       seq_printf(p, "%10lu ", ipi_data[cpu].stats[i]);
+                       seq_printf(p, "%10u ", irq_desc_kstat_cpu(ipi_desc[i], cpu));
                seq_printf(p, " %s\n", ipi_names[i]);
        }
 }
index ddb2afb..00b5391 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/numa.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
-#include <asm/sbi.h>
 #include <asm/smp.h>
 
 #include "head.h"
@@ -158,12 +157,12 @@ asmlinkage __visible void smp_callin(void)
        struct mm_struct *mm = &init_mm;
        unsigned int curr_cpuid = smp_processor_id();
 
-       riscv_clear_ipi();
-
        /* All kernel threads share the same mm context.  */
        mmgrab(mm);
        current->active_mm = mm;
 
+       riscv_ipi_enable();
+
        store_cpu_topology(curr_cpuid);
        notify_cpu_starting(curr_cpuid);
        numa_add_cpu(curr_cpuid);
index fcd6145..20cec5e 100644 (file)
@@ -19,7 +19,7 @@ void flush_icache_all(void)
 {
        local_flush_icache_all();
 
-       if (IS_ENABLED(CONFIG_RISCV_SBI))
+       if (IS_ENABLED(CONFIG_RISCV_SBI) && !riscv_use_ipi_for_rfence())
                sbi_remote_fence_i(NULL);
        else
                on_each_cpu(ipi_remote_fence_i, NULL, 1);
@@ -67,7 +67,8 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
                 * with flush_icache_deferred().
                 */
                smp_mb();
-       } else if (IS_ENABLED(CONFIG_RISCV_SBI)) {
+       } else if (IS_ENABLED(CONFIG_RISCV_SBI) &&
+                  !riscv_use_ipi_for_rfence()) {
                sbi_remote_fence_i(&others);
        } else {
                on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1);
index 0f784e3..12e22e7 100644 (file)
@@ -22,7 +22,7 @@ DEFINE_STATIC_KEY_FALSE(use_asid_allocator);
 
 static unsigned long asid_bits;
 static unsigned long num_asids;
-static unsigned long asid_mask;
+unsigned long asid_mask;
 
 static atomic_long_t current_version;
 
index 37ed760..77be59a 100644 (file)
@@ -23,14 +23,62 @@ static inline void local_flush_tlb_page_asid(unsigned long addr,
                        : "memory");
 }
 
+static inline void local_flush_tlb_range(unsigned long start,
+               unsigned long size, unsigned long stride)
+{
+       if (size <= stride)
+               local_flush_tlb_page(start);
+       else
+               local_flush_tlb_all();
+}
+
+static inline void local_flush_tlb_range_asid(unsigned long start,
+               unsigned long size, unsigned long stride, unsigned long asid)
+{
+       if (size <= stride)
+               local_flush_tlb_page_asid(start, asid);
+       else
+               local_flush_tlb_all_asid(asid);
+}
+
+static void __ipi_flush_tlb_all(void *info)
+{
+       local_flush_tlb_all();
+}
+
 void flush_tlb_all(void)
 {
-       sbi_remote_sfence_vma(NULL, 0, -1);
+       if (riscv_use_ipi_for_rfence())
+               on_each_cpu(__ipi_flush_tlb_all, NULL, 1);
+       else
+               sbi_remote_sfence_vma(NULL, 0, -1);
+}
+
+struct flush_tlb_range_data {
+       unsigned long asid;
+       unsigned long start;
+       unsigned long size;
+       unsigned long stride;
+};
+
+static void __ipi_flush_tlb_range_asid(void *info)
+{
+       struct flush_tlb_range_data *d = info;
+
+       local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
+}
+
+static void __ipi_flush_tlb_range(void *info)
+{
+       struct flush_tlb_range_data *d = info;
+
+       local_flush_tlb_range(d->start, d->size, d->stride);
 }
 
-static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
-                                 unsigned long size, unsigned long stride)
+static void __flush_tlb_range(struct mm_struct *mm, unsigned long start,
+                             unsigned long size, unsigned long stride)
 {
+       struct flush_tlb_range_data ftd;
        struct cpumask *cmask = mm_cpumask(mm);
        unsigned int cpuid;
        bool broadcast;
@@ -42,22 +90,37 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
        /* check if the tlbflush needs to be sent to other CPUs */
        broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
        if (static_branch_unlikely(&use_asid_allocator)) {
-               unsigned long asid = atomic_long_read(&mm->context.id);
+               unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
 
                if (broadcast) {
-                       sbi_remote_sfence_vma_asid(cmask, start, size, asid);
-               } else if (size <= stride) {
-                       local_flush_tlb_page_asid(start, asid);
+                       if (riscv_use_ipi_for_rfence()) {
+                               ftd.asid = asid;
+                               ftd.start = start;
+                               ftd.size = size;
+                               ftd.stride = stride;
+                               on_each_cpu_mask(cmask,
+                                                __ipi_flush_tlb_range_asid,
+                                                &ftd, 1);
+                       } else
+                               sbi_remote_sfence_vma_asid(cmask,
+                                                          start, size, asid);
                } else {
-                       local_flush_tlb_all_asid(asid);
+                       local_flush_tlb_range_asid(start, size, stride, asid);
                }
        } else {
                if (broadcast) {
-                       sbi_remote_sfence_vma(cmask, start, size);
-               } else if (size <= stride) {
-                       local_flush_tlb_page(start);
+                       if (riscv_use_ipi_for_rfence()) {
+                               ftd.asid = 0;
+                               ftd.start = start;
+                               ftd.size = size;
+                               ftd.stride = stride;
+                               on_each_cpu_mask(cmask,
+                                                __ipi_flush_tlb_range,
+                                                &ftd, 1);
+                       } else
+                               sbi_remote_sfence_vma(cmask, start, size);
                } else {
-                       local_flush_tlb_all();
+                       local_flush_tlb_range(start, size, stride);
                }
        }
 
@@ -66,23 +129,23 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
-       __sbi_tlb_flush_range(mm, 0, -1, PAGE_SIZE);
+       __flush_tlb_range(mm, 0, -1, PAGE_SIZE);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
 {
-       __sbi_tlb_flush_range(vma->vm_mm, addr, PAGE_SIZE, PAGE_SIZE);
+       __flush_tlb_range(vma->vm_mm, addr, PAGE_SIZE, PAGE_SIZE);
 }
 
 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                     unsigned long end)
 {
-       __sbi_tlb_flush_range(vma->vm_mm, start, end - start, PAGE_SIZE);
+       __flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE);
 }
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
                        unsigned long end)
 {
-       __sbi_tlb_flush_range(vma->vm_mm, start, end - start, PMD_SIZE);
+       __flush_tlb_range(vma->vm_mm, start, end - start, PMD_SIZE);
 }
 #endif
index 8c45b19..bccea57 100644 (file)
@@ -923,6 +923,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
 
                /* Event overflow */
                handled++;
+               status &= ~mask;
                perf_sample_data_init(&data, 0, hwc->last_period);
 
                if (!x86_perf_event_set_period(event))
@@ -933,8 +934,6 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
 
                if (perf_event_overflow(event, &data, regs))
                        x86_pmu_stop(event, 0);
-
-               status &= ~mask;
        }
 
        /*
index 714166c..0bab497 100644 (file)
@@ -1118,21 +1118,20 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
        zerofrom = offsetof(struct xregs_state, extended_state_area);
 
        /*
-        * The ptrace buffer is in non-compacted XSAVE format.  In
-        * non-compacted format disabled features still occupy state space,
-        * but there is no state to copy from in the compacted
-        * init_fpstate. The gap tracking will zero these states.
-        */
-       mask = fpstate->user_xfeatures;
-
-       /*
-        * Dynamic features are not present in init_fpstate. When they are
-        * in an all zeros init state, remove those from 'mask' to zero
-        * those features in the user buffer instead of retrieving them
-        * from init_fpstate.
+        * This 'mask' indicates which states to copy from fpstate.
+        * Those extended states that are not present in fpstate are
+        * either disabled or initialized:
+        *
+        * In non-compacted format, disabled features still occupy
+        * state space but there is no state to copy from in the
+        * compacted init_fpstate. The gap tracking will zero these
+        * states.
+        *
+        * The extended features have an all zeroes init state. Thus,
+        * remove them from 'mask' to zero those features in the user
+        * buffer instead of retrieving them from init_fpstate.
         */
-       if (fpu_state_size_dynamic())
-               mask &= (header.xfeatures | xinit->header.xcomp_bv);
+       mask = header.xfeatures;
 
        for_each_extended_xfeature(i, mask) {
                /*
@@ -1151,9 +1150,8 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
                        pkru.pkru = pkru_val;
                        membuf_write(&to, &pkru, sizeof(pkru));
                } else {
-                       copy_feature(header.xfeatures & BIT_ULL(i), &to,
+                       membuf_write(&to,
                                     __raw_xsave_addr(xsave, i),
-                                    __raw_xsave_addr(xinit, i),
                                     xstate_sizes[i]);
                }
                /*
index 7316a82..e91500a 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/fixmap.h>
 #include <asm/desc.h>
 #include <asm/kasan.h>
+#include <asm/setup.h>
 
 static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage);
 
@@ -29,6 +30,12 @@ static __init void init_cea_offsets(void)
        unsigned int max_cea;
        unsigned int i, j;
 
+       if (!kaslr_enabled()) {
+               for_each_possible_cpu(i)
+                       per_cpu(_cea_offset, i) = i;
+               return;
+       }
+
        max_cea = (CPU_ENTRY_AREA_MAP_SIZE - PAGE_SIZE) / CPU_ENTRY_AREA_SIZE;
 
        /* O(sodding terrible) */
index 1da44ac..ada3868 100644 (file)
@@ -48,7 +48,7 @@ void __init xen_pvh_init(struct boot_params *boot_params)
                struct xen_platform_op op = {
                        .cmd = XENPF_get_dom0_console,
                };
-               long ret = HYPERVISOR_platform_op(&op);
+               int ret = HYPERVISOR_platform_op(&op);
 
                if (ret > 0)
                        xen_init_vga(&op.u.dom0_console,
index 4fa769c..f0d4ff3 100644 (file)
@@ -79,16 +79,16 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
                }
 
                if (sinfo->msgdigest_len != sig->digest_size) {
-                       pr_debug("Sig %u: Invalid digest size (%u)\n",
-                                sinfo->index, sinfo->msgdigest_len);
+                       pr_warn("Sig %u: Invalid digest size (%u)\n",
+                               sinfo->index, sinfo->msgdigest_len);
                        ret = -EBADMSG;
                        goto error;
                }
 
                if (memcmp(sig->digest, sinfo->msgdigest,
                           sinfo->msgdigest_len) != 0) {
-                       pr_debug("Sig %u: Message digest doesn't match\n",
-                                sinfo->index);
+                       pr_warn("Sig %u: Message digest doesn't match\n",
+                               sinfo->index);
                        ret = -EKEYREJECTED;
                        goto error;
                }
@@ -478,7 +478,7 @@ int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
                               const void *data, size_t datalen)
 {
        if (pkcs7->data) {
-               pr_debug("Data already supplied\n");
+               pr_warn("Data already supplied\n");
                return -EINVAL;
        }
        pkcs7->data = data;
index 7553ab1..22beaf2 100644 (file)
@@ -74,7 +74,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
                break;
 
        default:
-               pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
+               pr_warn("Unknown PEOPT magic = %04hx\n", pe32->magic);
                return -ELIBBAD;
        }
 
@@ -95,7 +95,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
        ctx->certs_size = ddir->certs.size;
 
        if (!ddir->certs.virtual_address || !ddir->certs.size) {
-               pr_debug("Unsigned PE binary\n");
+               pr_warn("Unsigned PE binary\n");
                return -ENODATA;
        }
 
@@ -127,7 +127,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
        unsigned len;
 
        if (ctx->sig_len < sizeof(wrapper)) {
-               pr_debug("Signature wrapper too short\n");
+               pr_warn("Signature wrapper too short\n");
                return -ELIBBAD;
        }
 
@@ -135,19 +135,23 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
        pr_debug("sig wrapper = { %x, %x, %x }\n",
                 wrapper.length, wrapper.revision, wrapper.cert_type);
 
-       /* Both pesign and sbsign round up the length of certificate table
-        * (in optional header data directories) to 8 byte alignment.
+       /* sbsign rounds up the length of certificate table (in optional
+        * header data directories) to 8 byte alignment.  However, the PE
+        * specification states that while entries are 8-byte aligned, this is
+        * not included in their length, and as a result, pesign has not
+        * rounded up since 0.110.
         */
-       if (round_up(wrapper.length, 8) != ctx->sig_len) {
-               pr_debug("Signature wrapper len wrong\n");
+       if (wrapper.length > ctx->sig_len) {
+               pr_warn("Signature wrapper bigger than sig len (%x > %x)\n",
+                       ctx->sig_len, wrapper.length);
                return -ELIBBAD;
        }
        if (wrapper.revision != WIN_CERT_REVISION_2_0) {
-               pr_debug("Signature is not revision 2.0\n");
+               pr_warn("Signature is not revision 2.0\n");
                return -ENOTSUPP;
        }
        if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
-               pr_debug("Signature certificate type is not PKCS\n");
+               pr_warn("Signature certificate type is not PKCS\n");
                return -ENOTSUPP;
        }
 
@@ -160,7 +164,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
        ctx->sig_offset += sizeof(wrapper);
        ctx->sig_len -= sizeof(wrapper);
        if (ctx->sig_len < 4) {
-               pr_debug("Signature data missing\n");
+               pr_warn("Signature data missing\n");
                return -EKEYREJECTED;
        }
 
@@ -194,7 +198,7 @@ check_len:
                return 0;
        }
 not_pkcs7:
-       pr_debug("Signature data not PKCS#7\n");
+       pr_warn("Signature data not PKCS#7\n");
        return -ELIBBAD;
 }
 
@@ -337,8 +341,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
        digest_size = crypto_shash_digestsize(tfm);
 
        if (digest_size != ctx->digest_len) {
-               pr_debug("Digest size mismatch (%zx != %x)\n",
-                        digest_size, ctx->digest_len);
+               pr_warn("Digest size mismatch (%zx != %x)\n",
+                       digest_size, ctx->digest_len);
                ret = -EBADMSG;
                goto error_no_desc;
        }
@@ -369,7 +373,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
         * PKCS#7 certificate.
         */
        if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
-               pr_debug("Digest mismatch\n");
+               pr_warn("Digest mismatch\n");
                ret = -EKEYREJECTED;
        } else {
                pr_debug("The digests match!\n");
index 1278969..4bd16b3 100644 (file)
@@ -263,6 +263,12 @@ static int __init acpi_processor_driver_init(void)
        if (acpi_disabled)
                return 0;
 
+       if (!cpufreq_register_notifier(&acpi_processor_notifier_block,
+                                      CPUFREQ_POLICY_NOTIFIER)) {
+               acpi_processor_cpufreq_init = true;
+               acpi_processor_ignore_ppc_init();
+       }
+
        result = driver_register(&acpi_processor_driver);
        if (result < 0)
                return result;
@@ -276,12 +282,6 @@ static int __init acpi_processor_driver_init(void)
        cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead",
                                  NULL, acpi_soft_cpu_dead);
 
-       if (!cpufreq_register_notifier(&acpi_processor_notifier_block,
-                                      CPUFREQ_POLICY_NOTIFIER)) {
-               acpi_processor_cpufreq_init = true;
-               acpi_processor_ignore_ppc_init();
-       }
-
        acpi_processor_throttling_init();
        return 0;
 err:
index e534fd4..b7c6287 100644 (file)
@@ -140,9 +140,13 @@ void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy)
                ret = freq_qos_add_request(&policy->constraints,
                                           &pr->thermal_req,
                                           FREQ_QOS_MAX, INT_MAX);
-               if (ret < 0)
+               if (ret < 0) {
                        pr_err("Failed to add freq constraint for CPU%d (%d)\n",
                               cpu, ret);
+                       continue;
+               }
+
+               thermal_cooling_device_update(pr->cdev);
        }
 }
 
@@ -153,8 +157,12 @@ void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
        for_each_cpu(cpu, policy->related_cpus) {
                struct acpi_processor *pr = per_cpu(processors, cpu);
 
-               if (pr)
-                       freq_qos_remove_request(&pr->thermal_req);
+               if (!pr)
+                       continue;
+
+               freq_qos_remove_request(&pr->thermal_req);
+
+               thermal_cooling_device_update(pr->cdev);
        }
 }
 #else                          /* ! CONFIG_CPU_FREQ */
index 7c9125d..7b4801c 100644 (file)
@@ -400,6 +400,13 @@ static const struct dmi_system_id medion_laptop[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "M17T"),
                },
        },
+       {
+               .ident = "MEDION S17413",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+                       DMI_MATCH(DMI_BOARD_NAME, "M1xA"),
+               },
+       },
        { }
 };
 
index 14d6d81..fd7cbce 100644 (file)
@@ -497,6 +497,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
        },
        {
         .callback = video_detect_force_native,
+        /* Acer Aspire 3830TG */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3830TG"),
+               },
+       },
+       {
+        .callback = video_detect_force_native,
         /* Acer Aspire 4810T */
         .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
index eec0cc2..e327a02 100644 (file)
@@ -2909,6 +2909,7 @@ close_card_oam(struct idt77252_dev *card)
 
                                recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
                        }
+                       kfree(vc);
                }
        }
 }
@@ -2952,6 +2953,15 @@ open_card_ubr0(struct idt77252_dev *card)
        return 0;
 }
 
+static void
+close_card_ubr0(struct idt77252_dev *card)
+{
+       struct vc_map *vc = card->vcs[0];
+
+       free_scq(card, vc->scq);
+       kfree(vc);
+}
+
 static int
 idt77252_dev_open(struct idt77252_dev *card)
 {
@@ -3001,6 +3011,7 @@ static void idt77252_dev_close(struct atm_dev *dev)
        struct idt77252_dev *card = dev->dev_data;
        u32 conf;
 
+       close_card_ubr0(card);
        close_card_oam(card);
 
        conf = SAR_CFG_RXPTH |  /* enable receive path           */
index d1d1c8d..c73cc57 100644 (file)
@@ -715,7 +715,8 @@ static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
        }
 }
 
-static void ubq_complete_io_cmd(struct ublk_io *io, int res)
+static void ubq_complete_io_cmd(struct ublk_io *io, int res,
+                               unsigned issue_flags)
 {
        /* mark this cmd owned by ublksrv */
        io->flags |= UBLK_IO_FLAG_OWNED_BY_SRV;
@@ -727,7 +728,7 @@ static void ubq_complete_io_cmd(struct ublk_io *io, int res)
        io->flags &= ~UBLK_IO_FLAG_ACTIVE;
 
        /* tell ublksrv one io request is coming */
-       io_uring_cmd_done(io->cmd, res, 0);
+       io_uring_cmd_done(io->cmd, res, 0, issue_flags);
 }
 
 #define UBLK_REQUEUE_DELAY_MS  3
@@ -744,7 +745,8 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
        mod_delayed_work(system_wq, &ubq->dev->monitor_work, 0);
 }
 
-static inline void __ublk_rq_task_work(struct request *req)
+static inline void __ublk_rq_task_work(struct request *req,
+                                      unsigned issue_flags)
 {
        struct ublk_queue *ubq = req->mq_hctx->driver_data;
        int tag = req->tag;
@@ -782,7 +784,7 @@ static inline void __ublk_rq_task_work(struct request *req)
                        pr_devel("%s: need get data. op %d, qid %d tag %d io_flags %x\n",
                                        __func__, io->cmd->cmd_op, ubq->q_id,
                                        req->tag, io->flags);
-                       ubq_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA);
+                       ubq_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA, issue_flags);
                        return;
                }
                /*
@@ -820,17 +822,18 @@ static inline void __ublk_rq_task_work(struct request *req)
                        mapped_bytes >> 9;
        }
 
-       ubq_complete_io_cmd(io, UBLK_IO_RES_OK);
+       ubq_complete_io_cmd(io, UBLK_IO_RES_OK, issue_flags);
 }
 
-static inline void ublk_forward_io_cmds(struct ublk_queue *ubq)
+static inline void ublk_forward_io_cmds(struct ublk_queue *ubq,
+                                       unsigned issue_flags)
 {
        struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds);
        struct ublk_rq_data *data, *tmp;
 
        io_cmds = llist_reverse_order(io_cmds);
        llist_for_each_entry_safe(data, tmp, io_cmds, node)
-               __ublk_rq_task_work(blk_mq_rq_from_pdu(data));
+               __ublk_rq_task_work(blk_mq_rq_from_pdu(data), issue_flags);
 }
 
 static inline void ublk_abort_io_cmds(struct ublk_queue *ubq)
@@ -842,12 +845,12 @@ static inline void ublk_abort_io_cmds(struct ublk_queue *ubq)
                __ublk_abort_rq(ubq, blk_mq_rq_from_pdu(data));
 }
 
-static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd)
+static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
 {
        struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
        struct ublk_queue *ubq = pdu->ubq;
 
-       ublk_forward_io_cmds(ubq);
+       ublk_forward_io_cmds(ubq, issue_flags);
 }
 
 static void ublk_rq_task_work_fn(struct callback_head *work)
@@ -856,8 +859,9 @@ static void ublk_rq_task_work_fn(struct callback_head *work)
                        struct ublk_rq_data, work);
        struct request *req = blk_mq_rq_from_pdu(data);
        struct ublk_queue *ubq = req->mq_hctx->driver_data;
+       unsigned issue_flags = IO_URING_F_UNLOCKED;
 
-       ublk_forward_io_cmds(ubq);
+       ublk_forward_io_cmds(ubq, issue_flags);
 }
 
 static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq)
@@ -1111,7 +1115,8 @@ static void ublk_cancel_queue(struct ublk_queue *ubq)
                struct ublk_io *io = &ubq->ios[i];
 
                if (io->flags & UBLK_IO_FLAG_ACTIVE)
-                       io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0);
+                       io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0,
+                                               IO_URING_F_UNLOCKED);
        }
 
        /* all io commands are canceled */
@@ -1351,7 +1356,7 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
        return -EIOCBQUEUED;
 
  out:
-       io_uring_cmd_done(cmd, ret, 0);
+       io_uring_cmd_done(cmd, ret, 0, issue_flags);
        pr_devel("%s: complete: cmd op %d, tag %d ret %x io_flags %x\n",
                        __func__, cmd_op, tag, ret, io->flags);
        return -EIOCBQUEUED;
@@ -1602,17 +1607,18 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
                set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
 
        get_device(&ub->cdev_dev);
+       ub->dev_info.state = UBLK_S_DEV_LIVE;
        ret = add_disk(disk);
        if (ret) {
                /*
                 * Has to drop the reference since ->free_disk won't be
                 * called in case of add_disk failure.
                 */
+               ub->dev_info.state = UBLK_S_DEV_DEAD;
                ublk_put_device(ub);
                goto out_put_disk;
        }
        set_bit(UB_STATE_USED, &ub->state);
-       ub->dev_info.state = UBLK_S_DEV_LIVE;
 out_put_disk:
        if (ret)
                put_disk(disk);
@@ -2233,7 +2239,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
        if (ub)
                ublk_put_device(ub);
  out:
-       io_uring_cmd_done(cmd, ret, 0);
+       io_uring_cmd_done(cmd, ret, 0, issue_flags);
        pr_devel("%s: cmd done ret %d cmd_op %x, dev id %d qid %d\n",
                        __func__, ret, cmd->cmd_op, header->dev_id, header->queue_id);
        return -EIOCBQUEUED;
index bede8b0..af77468 100644 (file)
 #define ECDSA_HEADER_LEN       320
 
 #define BTINTEL_PPAG_NAME   "PPAG"
-#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB"
+
+/* structure to store the PPAG data read from ACPI table */
+struct btintel_ppag {
+       u32     domain;
+       u32     mode;
+       acpi_status status;
+       struct hci_dev *hdev;
+};
 
 #define CMD_WRITE_BOOT_PARAMS  0xfc0e
 struct cmd_write_boot_params {
@@ -1295,17 +1302,16 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
        if (ACPI_FAILURE(status)) {
-               bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
+               bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status));
                return status;
        }
 
-       if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer,
-                   strlen(BTINTEL_PPAG_PREFIX))) {
+       len = strlen(string.pointer);
+       if (len < strlen(BTINTEL_PPAG_NAME)) {
                kfree(string.pointer);
                return AE_OK;
        }
 
-       len = strlen(string.pointer);
        if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) {
                kfree(string.pointer);
                return AE_OK;
@@ -1314,7 +1320,8 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
        if (ACPI_FAILURE(status)) {
-               bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
+               ppag->status = status;
+               bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status));
                return status;
        }
 
@@ -1323,8 +1330,9 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) {
                kfree(buffer.pointer);
-               bt_dev_warn(hdev, "Invalid object type: %d or package count: %d",
+               bt_dev_warn(hdev, "PPAG-BT: Invalid object type: %d or package count: %d",
                            p->type, p->package.count);
+               ppag->status = AE_ERROR;
                return AE_ERROR;
        }
 
@@ -1335,6 +1343,7 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        ppag->domain = (u32)p->package.elements[0].integer.value;
        ppag->mode = (u32)p->package.elements[1].integer.value;
+       ppag->status = AE_OK;
        kfree(buffer.pointer);
        return AE_CTRL_TERMINATE;
 }
@@ -2314,12 +2323,12 @@ error:
 
 static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver)
 {
-       acpi_status status;
        struct btintel_ppag ppag;
        struct sk_buff *skb;
        struct btintel_loc_aware_reg ppag_cmd;
+       acpi_handle handle;
 
-    /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
+       /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
        switch (ver->cnvr_top & 0xFFF) {
        case 0x504:     /* Hrp2 */
        case 0x202:     /* Jfp2 */
@@ -2327,29 +2336,35 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver
                return;
        }
 
+       handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
+       if (!handle) {
+               bt_dev_info(hdev, "No support for BT device in ACPI firmware");
+               return;
+       }
+
        memset(&ppag, 0, sizeof(ppag));
 
        ppag.hdev = hdev;
-       status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-                                    ACPI_UINT32_MAX, NULL,
-                                    btintel_ppag_callback, &ppag, NULL);
+       ppag.status = AE_NOT_FOUND;
+       acpi_walk_namespace(ACPI_TYPE_PACKAGE, handle, 1, NULL,
+                           btintel_ppag_callback, &ppag, NULL);
 
-       if (ACPI_FAILURE(status)) {
-               /* Do not log warning message if ACPI entry is not found */
-               if (status == AE_NOT_FOUND)
+       if (ACPI_FAILURE(ppag.status)) {
+               if (ppag.status == AE_NOT_FOUND) {
+                       bt_dev_dbg(hdev, "PPAG-BT: ACPI entry not found");
                        return;
-               bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status));
+               }
                return;
        }
 
        if (ppag.domain != 0x12) {
-               bt_dev_warn(hdev, "PPAG-BT Domain disabled");
+               bt_dev_warn(hdev, "PPAG-BT: domain is not bluetooth");
                return;
        }
 
        /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */
        if (!(ppag.mode & BIT(0))) {
-               bt_dev_dbg(hdev, "PPAG disabled");
+               bt_dev_dbg(hdev, "PPAG-BT: disabled");
                return;
        }
 
index 8e7da87..8fdb65b 100644 (file)
@@ -137,13 +137,6 @@ struct intel_offload_use_cases {
        __u8    preset[8];
 } __packed;
 
-/* structure to store the PPAG data read from ACPI table */
-struct btintel_ppag {
-       u32     domain;
-       u32     mode;
-       struct hci_dev *hdev;
-};
-
 struct btintel_loc_aware_reg {
        __le32 mcc;
        __le32 sel;
index 2acb719..11c7e04 100644 (file)
@@ -122,6 +122,21 @@ static int btqcomsmd_setup(struct hci_dev *hdev)
        return 0;
 }
 
+static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+       int ret;
+
+       ret = qca_set_bdaddr_rome(hdev, bdaddr);
+       if (ret)
+               return ret;
+
+       /* The firmware stops responding for a while after setting the bdaddr,
+        * causing timeouts for subsequent commands. Sleep a bit to avoid this.
+        */
+       usleep_range(1000, 10000);
+       return 0;
+}
+
 static int btqcomsmd_probe(struct platform_device *pdev)
 {
        struct btqcomsmd *btq;
@@ -162,7 +177,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
        hdev->close = btqcomsmd_close;
        hdev->send = btqcomsmd_send;
        hdev->setup = btqcomsmd_setup;
-       hdev->set_bdaddr = qca_set_bdaddr_rome;
+       hdev->set_bdaddr = btqcomsmd_set_bdaddr;
 
        ret = hci_register_dev(hdev);
        if (ret < 0)
index 795be33..0289360 100644 (file)
@@ -354,6 +354,7 @@ static void btsdio_remove(struct sdio_func *func)
 
        BT_DBG("func %p", func);
 
+       cancel_work_sync(&data->work);
        if (!data)
                return;
 
index 18bc947..5c53615 100644 (file)
@@ -1050,21 +1050,11 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
                hci_skb_expect(skb) -= len;
 
                if (skb->len == HCI_ACL_HDR_SIZE) {
-                       __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
                        __le16 dlen = hci_acl_hdr(skb)->dlen;
-                       __u8 type;
 
                        /* Complete ACL header */
                        hci_skb_expect(skb) = __le16_to_cpu(dlen);
 
-                       /* Detect if ISO packet has been sent over bulk */
-                       if (hci_conn_num(data->hdev, ISO_LINK)) {
-                               type = hci_conn_lookup_type(data->hdev,
-                                                           hci_handle(handle));
-                               if (type == ISO_LINK)
-                                       hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
-                       }
-
                        if (skb_tailroom(skb) < hci_skb_expect(skb)) {
                                kfree_skb(skb);
                                skb = NULL;
index 2a6b4f6..36d4248 100644 (file)
@@ -204,8 +204,8 @@ static int weim_parse_dt(struct platform_device *pdev)
        const struct of_device_id *of_id = of_match_device(weim_id_table,
                                                           &pdev->dev);
        const struct imx_weim_devtype *devtype = of_id->data;
+       int ret = 0, have_child = 0;
        struct device_node *child;
-       int ret, have_child = 0;
        struct weim_priv *priv;
        void __iomem *base;
        u32 reg;
index 6cfe2ab..9a55e73 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/sched_clock.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/smp.h>
 #include <linux/timex.h>
@@ -31,6 +34,7 @@
 
 /* CLINT manages IPI and Timer for RISC-V M-mode  */
 static u32 __iomem *clint_ipi_base;
+static unsigned int clint_ipi_irq;
 static u64 __iomem *clint_timer_cmp;
 static u64 __iomem *clint_timer_val;
 static unsigned long clint_timer_freq;
@@ -41,12 +45,10 @@ u64 __iomem *clint_time_val;
 EXPORT_SYMBOL(clint_time_val);
 #endif
 
-static void clint_send_ipi(const struct cpumask *target)
+#ifdef CONFIG_SMP
+static void clint_send_ipi(unsigned int cpu)
 {
-       unsigned int cpu;
-
-       for_each_cpu(cpu, target)
-               writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu));
+       writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu));
 }
 
 static void clint_clear_ipi(void)
@@ -54,10 +56,18 @@ static void clint_clear_ipi(void)
        writel(0, clint_ipi_base + cpuid_to_hartid_map(smp_processor_id()));
 }
 
-static struct riscv_ipi_ops clint_ipi_ops = {
-       .ipi_inject = clint_send_ipi,
-       .ipi_clear = clint_clear_ipi,
-};
+static void clint_ipi_interrupt(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(chip, desc);
+
+       clint_clear_ipi();
+       ipi_mux_process();
+
+       chained_irq_exit(chip, desc);
+}
+#endif
 
 #ifdef CONFIG_64BIT
 #define clint_get_cycles()     readq_relaxed(clint_timer_val)
@@ -125,12 +135,19 @@ static int clint_timer_starting_cpu(unsigned int cpu)
 
        enable_percpu_irq(clint_timer_irq,
                          irq_get_trigger_type(clint_timer_irq));
+       enable_percpu_irq(clint_ipi_irq,
+                         irq_get_trigger_type(clint_ipi_irq));
        return 0;
 }
 
 static int clint_timer_dying_cpu(unsigned int cpu)
 {
        disable_percpu_irq(clint_timer_irq);
+       /*
+        * Don't disable IPI when CPU goes offline because
+        * the masking/unmasking of virtual IPIs is done
+        * via generic IPI-Mux
+        */
        return 0;
 }
 
@@ -170,6 +187,12 @@ static int __init clint_timer_init_dt(struct device_node *np)
                        return -ENODEV;
                }
 
+               /* Find parent irq domain and map ipi irq */
+               if (!clint_ipi_irq &&
+                   oirq.args[0] == RV_IRQ_SOFT &&
+                   irq_find_host(oirq.np))
+                       clint_ipi_irq = irq_of_parse_and_map(np, i);
+
                /* Find parent irq domain and map timer irq */
                if (!clint_timer_irq &&
                    oirq.args[0] == RV_IRQ_TIMER &&
@@ -177,9 +200,9 @@ static int __init clint_timer_init_dt(struct device_node *np)
                        clint_timer_irq = irq_of_parse_and_map(np, i);
        }
 
-       /* If CLINT timer irq not found then fail */
-       if (!clint_timer_irq) {
-               pr_err("%pOFP: timer irq not found\n", np);
+       /* If CLINT ipi or timer irq not found then fail */
+       if (!clint_ipi_irq || !clint_timer_irq) {
+               pr_err("%pOFP: ipi/timer irq not found\n", np);
                return -ENODEV;
        }
 
@@ -219,6 +242,19 @@ static int __init clint_timer_init_dt(struct device_node *np)
                goto fail_iounmap;
        }
 
+#ifdef CONFIG_SMP
+       rc = ipi_mux_create(BITS_PER_BYTE, clint_send_ipi);
+       if (rc <= 0) {
+               pr_err("unable to create muxed IPIs\n");
+               rc = (rc < 0) ? rc : -ENODEV;
+               goto fail_free_irq;
+       }
+
+       irq_set_chained_handler(clint_ipi_irq, clint_ipi_interrupt);
+       riscv_ipi_set_virq_range(rc, BITS_PER_BYTE, true);
+       clint_clear_ipi();
+#endif
+
        rc = cpuhp_setup_state(CPUHP_AP_CLINT_TIMER_STARTING,
                                "clockevents/clint/timer:starting",
                                clint_timer_starting_cpu,
@@ -228,13 +264,10 @@ static int __init clint_timer_init_dt(struct device_node *np)
                goto fail_free_irq;
        }
 
-       riscv_set_ipi_ops(&clint_ipi_ops);
-       clint_clear_ipi();
-
        return 0;
 
 fail_free_irq:
-       free_irq(clint_timer_irq, &clint_clock_event);
+       free_percpu_irq(clint_timer_irq, &clint_clock_event);
 fail_iounmap:
        iounmap(base);
        return rc;
index 73140b8..c15928b 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/device.h>
-#include <linux/of.h>
 
 #include "common.h"
 
@@ -436,7 +435,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
        /* Nothing to do. */
        if (!phead) {
                mutex_unlock(&scmi_requested_devices_mtx);
-               return scmi_dev;
+               return NULL;
        }
 
        /* Walk the list of requested devices for protocol and create them */
index d21c7ea..dbc474f 100644 (file)
@@ -2221,8 +2221,8 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
        hash_init(info->pending_xfers);
 
        /* Allocate a bitmask sized to hold MSG_TOKEN_MAX tokens */
-       info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(MSG_TOKEN_MAX),
-                                             sizeof(long), GFP_KERNEL);
+       info->xfer_alloc_table = devm_bitmap_zalloc(dev, MSG_TOKEN_MAX,
+                                                   GFP_KERNEL);
        if (!info->xfer_alloc_table)
                return -ENOMEM;
 
@@ -2657,6 +2657,7 @@ static int scmi_probe(struct platform_device *pdev)
        struct scmi_handle *handle;
        const struct scmi_desc *desc;
        struct scmi_info *info;
+       bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
        struct device *dev = &pdev->dev;
        struct device_node *child, *np = dev->of_node;
 
@@ -2731,16 +2732,13 @@ static int scmi_probe(struct platform_device *pdev)
                        dev_warn(dev, "Failed to setup SCMI debugfs.\n");
 
                if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
-                       bool coex =
-                             IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
-
                        ret = scmi_debugfs_raw_mode_setup(info);
                        if (!coex) {
                                if (ret)
                                        goto clear_dev_req_notifier;
 
-                               /* Bail out anyway when coex enabled */
-                               return ret;
+                               /* Bail out anyway when coex disabled. */
+                               return 0;
                        }
 
                        /* Coex enabled, carry on in any case. */
@@ -2764,6 +2762,8 @@ static int scmi_probe(struct platform_device *pdev)
        ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
        if (ret) {
                dev_err(dev, "unable to communicate with SCMI\n");
+               if (coex)
+                       return 0;
                goto notification_exit;
        }
 
index 0d9c953..112c285 100644 (file)
@@ -52,6 +52,39 @@ static bool mailbox_chan_available(struct device_node *of_node, int idx)
                                           "#mbox-cells", idx, NULL);
 }
 
+static int mailbox_chan_validate(struct device *cdev)
+{
+       int num_mb, num_sh, ret = 0;
+       struct device_node *np = cdev->of_node;
+
+       num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+       num_sh = of_count_phandle_with_args(np, "shmem", NULL);
+       /* Bail out if mboxes and shmem descriptors are inconsistent */
+       if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) {
+               dev_warn(cdev, "Invalid channel descriptor for '%s'\n",
+                        of_node_full_name(np));
+               return -EINVAL;
+       }
+
+       if (num_sh > 1) {
+               struct device_node *np_tx, *np_rx;
+
+               np_tx = of_parse_phandle(np, "shmem", 0);
+               np_rx = of_parse_phandle(np, "shmem", 1);
+               /* SCMI Tx and Rx shared mem areas have to be distinct */
+               if (!np_tx || !np_rx || np_tx == np_rx) {
+                       dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
+                                of_node_full_name(np));
+                       ret = -EINVAL;
+               }
+
+               of_node_put(np_tx);
+               of_node_put(np_rx);
+       }
+
+       return ret;
+}
+
 static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                              bool tx)
 {
@@ -64,6 +97,10 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        resource_size_t size;
        struct resource res;
 
+       ret = mailbox_chan_validate(cdev);
+       if (ret)
+               return ret;
+
        smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
        if (!smbox)
                return -ENOMEM;
index f54e6fd..f80a9af 100644 (file)
@@ -215,6 +215,14 @@ efi_earlycon_write(struct console *con, const char *str, unsigned int num)
        }
 }
 
+static bool __initdata fb_probed;
+
+void __init efi_earlycon_reprobe(void)
+{
+       if (fb_probed)
+               setup_earlycon("efifb");
+}
+
 static int __init efi_earlycon_setup(struct earlycon_device *device,
                                     const char *opt)
 {
@@ -222,15 +230,17 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
        u16 xres, yres;
        u32 i;
 
-       if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+       fb_wb = opt && !strcmp(opt, "ram");
+
+       if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) {
+               fb_probed = true;
                return -ENODEV;
+       }
 
        fb_base = screen_info.lfb_base;
        if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
                fb_base |= (u64)screen_info.ext_lfb_base << 32;
 
-       fb_wb = opt && !strcmp(opt, "ram");
-
        si = &screen_info;
        xres = si->lfb_width;
        yres = si->lfb_height;
index 2c16080..ef0820f 100644 (file)
@@ -72,6 +72,9 @@ static void __init init_screen_info(void)
                if (memblock_is_map_memory(screen_info.lfb_base))
                        memblock_mark_nomap(screen_info.lfb_base,
                                            screen_info.lfb_size);
+
+               if (IS_ENABLED(CONFIG_EFI_EARLYCON))
+                       efi_earlycon_reprobe();
        }
 }
 
index 43e9a4c..ccdd6a1 100644 (file)
@@ -44,4 +44,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
 $(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
        $(call if_changed,objcopy)
 
-targets += zboot-header.o vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
+targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
index d4a6b12..770b8ec 100644 (file)
@@ -85,8 +85,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                }
        }
 
-       if (image->image_base != _text)
+       if (image->image_base != _text) {
                efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
+               image->image_base = _text;
+       }
 
        if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN))
                efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n",
@@ -139,6 +141,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        *image_addr = *reserve_addr;
        memcpy((void *)*image_addr, _text, kernel_size);
        caches_clean_inval_pou(*image_addr, *image_addr + kernel_codesize);
+       efi_remap_image(*image_addr, *reserve_size, kernel_codesize);
 
        return EFI_SUCCESS;
 }
index 3997702..8aad8c4 100644 (file)
 
 static bool system_needs_vamap(void)
 {
-       const u8 *type1_family = efi_get_smbios_string(1, family);
+       const struct efi_smbios_type4_record *record;
+       const u32 __aligned(1) *socid;
+       const u8 *version;
 
        /*
         * Ampere eMAG, Altra, and Altra Max machines crash in SetTime() if
-        * SetVirtualAddressMap() has not been called prior.
+        * SetVirtualAddressMap() has not been called prior. Most Altra systems
+        * can be identified by the SMCCC soc ID, which is conveniently exposed
+        * via the type 4 SMBIOS records. Otherwise, test the processor version
+        * field. eMAG systems all appear to have the processor version field
+        * set to "eMAG".
         */
-       if (!type1_family || (
-           strcmp(type1_family, "eMAG") &&
-           strcmp(type1_family, "Altra") &&
-           strcmp(type1_family, "Altra Max")))
+       record = (struct efi_smbios_type4_record *)efi_get_smbios_record(4);
+       if (!record)
                return false;
 
-       efi_warn("Working around broken SetVirtualAddressMap()\n");
-       return true;
+       socid = (u32 *)record->processor_id;
+       switch (*socid & 0xffff000f) {
+               static char const altra[] = "Ampere(TM) Altra(TM) Processor";
+               static char const emag[] = "eMAG";
+
+       default:
+               version = efi_get_smbios_string(&record->header, 4,
+                                               processor_version);
+               if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
+                                strncmp(version, emag, sizeof(emag) - 1)))
+                       break;
+
+               fallthrough;
+
+       case 0x0a160001:        // Altra
+       case 0x0a160002:        // Altra Max
+               efi_warn("Working around broken SetVirtualAddressMap()\n");
+               return true;
+       }
+
+       return false;
 }
 
 efi_status_t check_platform_features(void)
index 5245c4f..cc4dcae 100644 (file)
@@ -5,6 +5,15 @@
 
 #include "efistub.h"
 
+static unsigned long screen_info_offset;
+
+struct screen_info *alloc_screen_info(void)
+{
+       if (IS_ENABLED(CONFIG_ARM))
+               return __alloc_screen_info();
+       return (void *)&screen_info + screen_info_offset;
+}
+
 /*
  * EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
  * LoongArch. This is the entrypoint that is described in the PE/COFF header
@@ -56,6 +65,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
                return status;
        }
 
+       screen_info_offset = image_addr - (unsigned long)image->image_base;
+
        status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
 
        efi_free(image_size, image_addr);
index 2955c1a..f9c1e8a 100644 (file)
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
 
-struct screen_info * __weak alloc_screen_info(void)
-{
-       return &screen_info;
-}
-
 void __weak free_screen_info(struct screen_info *si)
 {
 }
index 6bd3bb8..148013b 100644 (file)
@@ -1062,6 +1062,7 @@ efi_enable_reset_attack_mitigation(void) { }
 void efi_retrieve_tpm2_eventlog(void);
 
 struct screen_info *alloc_screen_info(void);
+struct screen_info *__alloc_screen_info(void);
 void free_screen_info(struct screen_info *si);
 
 void efi_cache_sync_image(unsigned long image_base,
@@ -1074,6 +1075,8 @@ struct efi_smbios_record {
        u16     handle;
 };
 
+const struct efi_smbios_record *efi_get_smbios_record(u8 type);
+
 struct efi_smbios_type1_record {
        struct efi_smbios_record        header;
 
@@ -1087,14 +1090,46 @@ struct efi_smbios_type1_record {
        u8                              family;
 };
 
-#define efi_get_smbios_string(__type, __name) ({                       \
-       int size = sizeof(struct efi_smbios_type ## __type ## _record); \
+struct efi_smbios_type4_record {
+       struct efi_smbios_record        header;
+
+       u8                              socket;
+       u8                              processor_type;
+       u8                              processor_family;
+       u8                              processor_manufacturer;
+       u8                              processor_id[8];
+       u8                              processor_version;
+       u8                              voltage;
+       u16                             external_clock;
+       u16                             max_speed;
+       u16                             current_speed;
+       u8                              status;
+       u8                              processor_upgrade;
+       u16                             l1_cache_handle;
+       u16                             l2_cache_handle;
+       u16                             l3_cache_handle;
+       u8                              serial_number;
+       u8                              asset_tag;
+       u8                              part_number;
+       u8                              core_count;
+       u8                              enabled_core_count;
+       u8                              thread_count;
+       u16                             processor_characteristics;
+       u16                             processor_family2;
+       u16                             core_count2;
+       u16                             enabled_core_count2;
+       u16                             thread_count2;
+       u16                             thread_enabled;
+};
+
+#define efi_get_smbios_string(__record, __type, __name) ({             \
        int off = offsetof(struct efi_smbios_type ## __type ## _record, \
                           __name);                                     \
-       __efi_get_smbios_string(__type, off, size);                     \
+       __efi_get_smbios_string((__record), __type, off);               \
 })
 
-const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
+const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
+                                 u8 type, int offset);
 
 void efi_remap_image(unsigned long image_base, unsigned alloc_size,
                     unsigned long code_size);
index 1692d19..32c7a54 100644 (file)
@@ -101,6 +101,7 @@ efi_status_t efi_random_alloc(unsigned long size,
         * to calculate the randomly chosen address, and allocate it directly
         * using EFI_ALLOCATE_ADDRESS.
         */
+       status = EFI_OUT_OF_RESOURCES;
        for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
                efi_memory_desc_t *md = (void *)map->map + map_offset;
                efi_physical_addr_t target;
index 8e76a8b..4be1c4d 100644 (file)
  * early, but it only works if the EFI stub is part of the core kernel image
  * itself. The zboot decompressor can only use the configuration table
  * approach.
- *
- * In order to support both methods from the same build of the EFI stub
- * library, provide this dummy global definition of struct screen_info. If it
- * is required to satisfy a link dependency, it means we need to override the
- * __weak alloc and free methods with the ones below, and those will be pulled
- * in as well.
  */
-struct screen_info screen_info;
 
 static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID;
 
-struct screen_info *alloc_screen_info(void)
+struct screen_info *__alloc_screen_info(void)
 {
        struct screen_info *si;
        efi_status_t status;
index 460418b..c217de2 100644 (file)
@@ -22,21 +22,30 @@ struct efi_smbios_protocol {
        u8 minor_version;
 };
 
-const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize)
+const struct efi_smbios_record *efi_get_smbios_record(u8 type)
 {
        struct efi_smbios_record *record;
        efi_smbios_protocol_t *smbios;
        efi_status_t status;
        u16 handle = 0xfffe;
-       const u8 *strtable;
 
        status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL,
                             (void **)&smbios) ?:
                 efi_call_proto(smbios, get_next, &handle, &type, &record, NULL);
        if (status != EFI_SUCCESS)
                return NULL;
+       return record;
+}
+
+const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
+                                 u8 type, int offset)
+{
+       const u8 *strtable;
+
+       if (!record)
+               return NULL;
 
-       strtable = (u8 *)record + recsize;
+       strtable = (u8 *)record + record->length;
        for (int i = 1; i < ((u8 *)record)[offset]; i++) {
                int len = strlen(strtable);
 
index ec4525d..445cb64 100644 (file)
@@ -63,7 +63,7 @@ __efistub_efi_zboot_header:
        .long           .Lefi_header_end - .Ldoshdr
        .long           0
        .short          IMAGE_SUBSYSTEM_EFI_APPLICATION
-       .short          0
+       .short          IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
 #ifdef CONFIG_64BIT
        .quad           0, 0, 0, 0
 #else
index ba234e0..6105e5e 100644 (file)
@@ -57,6 +57,11 @@ void __weak efi_cache_sync_image(unsigned long image_base,
        // executable code loaded into memory to be safe for execution.
 }
 
+struct screen_info *alloc_screen_info(void)
+{
+       return __alloc_screen_info();
+}
+
 asmlinkage efi_status_t __efiapi
 efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
 {
index f06fdac..456d0e5 100644 (file)
@@ -272,6 +272,14 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
                                        "IdeaPad Duet 3 10IGL5"),
                },
        },
+       {
+               /* Lenovo Yoga Book X91F / X91L */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       /* Non exact match to match F + L versions */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
+               },
+       },
        {},
 };
 
@@ -341,7 +349,7 @@ static const struct fwnode_operations efifb_fwnode_ops = {
 #ifdef CONFIG_EFI
 static struct fwnode_handle efifb_fwnode;
 
-__init void sysfb_apply_efi_quirks(struct platform_device *pd)
+__init void sysfb_apply_efi_quirks(void)
 {
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
            !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
@@ -355,7 +363,10 @@ __init void sysfb_apply_efi_quirks(struct platform_device *pd)
                screen_info.lfb_height = temp;
                screen_info.lfb_linelength = 4 * screen_info.lfb_width;
        }
+}
 
+__init void sysfb_set_efifb_fwnode(struct platform_device *pd)
+{
        if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
                fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
                pd->dev.fwnode = &efifb_fwnode;
index 468d4d5..b1e11f8 100644 (file)
@@ -1479,7 +1479,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
 
        init_completion(&__scm->waitq_comp);
 
-       irq = platform_get_irq(pdev, 0);
+       irq = platform_get_irq_optional(pdev, 0);
        if (irq < 0) {
                if (irq != -ENXIO)
                        return irq;
index 60ccf3e..db818f9 100644 (file)
@@ -17,9 +17,13 @@ static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
 
 bool __ro_after_init smccc_trng_available = false;
 u64 __ro_after_init smccc_has_sve_hint = false;
+s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED;
+s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED;
 
 void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
 {
+       struct arm_smccc_res res;
+
        smccc_version = version;
        smccc_conduit = conduit;
 
@@ -27,6 +31,18 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
        if (IS_ENABLED(CONFIG_ARM64_SVE) &&
            smccc_version >= ARM_SMCCC_VERSION_1_3)
                smccc_has_sve_hint = true;
+
+       if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
+           (smccc_conduit != SMCCC_CONDUIT_NONE)) {
+               arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+                                    ARM_SMCCC_ARCH_SOC_ID, &res);
+               if ((s32)res.a0 >= 0) {
+                       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 0, &res);
+                       smccc_soc_id_version = (s32)res.a0;
+                       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 1, &res);
+                       smccc_soc_id_revision = (s32)res.a0;
+               }
+       }
 }
 
 enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void)
@@ -44,6 +60,16 @@ u32 arm_smccc_get_version(void)
 }
 EXPORT_SYMBOL_GPL(arm_smccc_get_version);
 
+s32 arm_smccc_get_soc_id_version(void)
+{
+       return smccc_soc_id_version;
+}
+
+s32 arm_smccc_get_soc_id_revision(void)
+{
+       return smccc_soc_id_revision;
+}
+
 static int __init smccc_devices_init(void)
 {
        struct platform_device *pdev;
index dd7c3d5..890eb45 100644 (file)
@@ -42,41 +42,23 @@ static int __init smccc_soc_init(void)
        if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
                return 0;
 
-       if (arm_smccc_1_1_get_conduit() == SMCCC_CONDUIT_NONE) {
-               pr_err("%s: invalid SMCCC conduit\n", __func__);
-               return -EOPNOTSUPP;
-       }
-
-       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
-                            ARM_SMCCC_ARCH_SOC_ID, &res);
-
-       if ((int)res.a0 == SMCCC_RET_NOT_SUPPORTED) {
+       soc_id_version = arm_smccc_get_soc_id_version();
+       if (soc_id_version == SMCCC_RET_NOT_SUPPORTED) {
                pr_info("ARCH_SOC_ID not implemented, skipping ....\n");
                return 0;
        }
 
-       if ((int)res.a0 < 0) {
-               pr_info("ARCH_FEATURES(ARCH_SOC_ID) returned error: %lx\n",
-                       res.a0);
-               return -EINVAL;
-       }
-
-       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 0, &res);
-       if ((int)res.a0 < 0) {
+       if (soc_id_version < 0) {
                pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0);
                return -EINVAL;
        }
 
-       soc_id_version = res.a0;
-
-       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 1, &res);
-       if ((int)res.a0 < 0) {
+       soc_id_rev = arm_smccc_get_soc_id_revision();
+       if (soc_id_rev < 0) {
                pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0);
                return -EINVAL;
        }
 
-       soc_id_rev = res.a0;
-
        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
        if (!soc_dev_attr)
                return -ENOMEM;
index 3fd3563..3c197db 100644 (file)
@@ -81,6 +81,8 @@ static __init int sysfb_init(void)
        if (disabled)
                goto unlock_mutex;
 
+       sysfb_apply_efi_quirks();
+
        /* try to create a simple-framebuffer device */
        compatible = sysfb_parse_mode(si, &mode);
        if (compatible) {
@@ -107,7 +109,7 @@ static __init int sysfb_init(void)
                goto unlock_mutex;
        }
 
-       sysfb_apply_efi_quirks(pd);
+       sysfb_set_efifb_fwnode(pd);
 
        ret = platform_device_add_data(pd, si, sizeof(*si));
        if (ret)
index ce9c007..82c64cb 100644 (file)
@@ -141,7 +141,7 @@ __init struct platform_device *sysfb_create_simplefb(const struct screen_info *s
        if (!pd)
                return ERR_PTR(-ENOMEM);
 
-       sysfb_apply_efi_quirks(pd);
+       sysfb_set_efifb_fwnode(pd);
 
        ret = platform_device_add_resources(pd, &res, 1);
        if (ret)
index 164141b..39018f7 100644 (file)
@@ -1272,6 +1272,7 @@ void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
 int amdgpu_device_pci_reset(struct amdgpu_device *adev);
 bool amdgpu_device_need_post(struct amdgpu_device *adev);
 bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
+bool amdgpu_device_aspm_support_quirk(void);
 
 void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,
                                  u64 num_vis_bytes);
@@ -1391,10 +1392,12 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
 int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
 
 void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
+bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
 void amdgpu_acpi_detect(void);
 #else
 static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
 static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
+static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
 static inline void amdgpu_acpi_detect(void) { }
 static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
 static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
@@ -1405,11 +1408,9 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
 bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);
-bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
 bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
 #else
 static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
-static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
 static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }
 #endif
 
index d4196fc..60b1857 100644 (file)
@@ -971,6 +971,29 @@ static bool amdgpu_atcs_pci_probe_handle(struct pci_dev *pdev)
        return true;
 }
 
+
+/**
+ * amdgpu_acpi_should_gpu_reset
+ *
+ * @adev: amdgpu_device_pointer
+ *
+ * returns true if should reset GPU, false if not
+ */
+bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
+{
+       if (adev->flags & AMD_IS_APU)
+               return false;
+
+       if (amdgpu_sriov_vf(adev))
+               return false;
+
+#if IS_ENABLED(CONFIG_SUSPEND)
+       return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
+#else
+       return true;
+#endif
+}
+
 /*
  * amdgpu_acpi_detect - detect ACPI ATIF/ATCS methods
  *
@@ -1043,24 +1066,6 @@ bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev)
 }
 
 /**
- * amdgpu_acpi_should_gpu_reset
- *
- * @adev: amdgpu_device_pointer
- *
- * returns true if should reset GPU, false if not
- */
-bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
-{
-       if (adev->flags & AMD_IS_APU)
-               return false;
-
-       if (amdgpu_sriov_vf(adev))
-               return false;
-
-       return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
-}
-
-/**
  * amdgpu_acpi_is_s0ix_active
  *
  * @adev: amdgpu_device_pointer
index da5b025..3d98fc2 100644 (file)
 
 #include <drm/drm_drv.h>
 
+#if IS_ENABLED(CONFIG_X86)
+#include <asm/intel-family.h>
+#endif
+
 MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
@@ -1356,6 +1360,17 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
        return pcie_aspm_enabled(adev->pdev);
 }
 
+bool amdgpu_device_aspm_support_quirk(void)
+{
+#if IS_ENABLED(CONFIG_X86)
+       struct cpuinfo_x86 *c = &cpu_data(0);
+
+       return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE);
+#else
+       return true;
+#endif
+}
+
 /* if we get transitioned to only one device, take VGA back */
 /**
  * amdgpu_device_vga_set_decode - enable/disable vga decode
index f5ffca2..ba5def3 100644 (file)
@@ -2467,7 +2467,10 @@ static int amdgpu_pmops_freeze(struct device *dev)
        adev->in_s4 = false;
        if (r)
                return r;
-       return amdgpu_asic_reset(adev);
+
+       if (amdgpu_acpi_should_gpu_reset(adev))
+               return amdgpu_asic_reset(adev);
+       return 0;
 }
 
 static int amdgpu_pmops_thaw(struct device *dev)
index faff4a3..f52d0ba 100644 (file)
@@ -678,6 +678,15 @@ void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring)
                ptr = &ring->fence_drv.fences[i];
                old = rcu_dereference_protected(*ptr, 1);
                if (old && old->ops == &amdgpu_job_fence_ops) {
+                       struct amdgpu_job *job;
+
+                       /* For non-scheduler bad job, i.e. failed ib test, we need to signal
+                        * it right here or we won't be able to track them in fence_drv
+                        * and they will remain unsignaled during sa_bo free.
+                        */
+                       job = container_of(old, struct amdgpu_job, hw_fence);
+                       if (!job->base.s_fence && !dma_fence_is_signaled(old))
+                               dma_fence_signal(old);
                        RCU_INIT_POINTER(*ptr, NULL);
                        dma_fence_put(old);
                }
index 3bf697a..ecf8ceb 100644 (file)
@@ -1287,6 +1287,11 @@ static int gfx_v11_0_sw_init(void *handle)
                break;
        }
 
+       /* Enable CG flag in one VF mode for enabling RLC safe mode enter/exit */
+       if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3) &&
+               amdgpu_sriov_is_pp_one_vf(adev))
+               adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG;
+
        /* EOP Event */
        r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
                              GFX_11_0_0__SRCID__CP_EOP_INTERRUPT,
@@ -4655,6 +4660,14 @@ static bool gfx_v11_0_check_soft_reset(void *handle)
        return false;
 }
 
+static int gfx_v11_0_post_soft_reset(void *handle)
+{
+       /**
+        * GFX soft reset will impact MES, need resume MES when do GFX soft reset
+        */
+       return amdgpu_mes_resume((struct amdgpu_device *)handle);
+}
+
 static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
        uint64_t clock;
@@ -6166,6 +6179,7 @@ static const struct amd_ip_funcs gfx_v11_0_ip_funcs = {
        .wait_for_idle = gfx_v11_0_wait_for_idle,
        .soft_reset = gfx_v11_0_soft_reset,
        .check_soft_reset = gfx_v11_0_check_soft_reset,
+       .post_soft_reset = gfx_v11_0_post_soft_reset,
        .set_clockgating_state = gfx_v11_0_set_clockgating_state,
        .set_powergating_state = gfx_v11_0_set_powergating_state,
        .get_clockgating_state = gfx_v11_0_get_clockgating_state,
index 22e25ca..ebe0e2d 100644 (file)
@@ -578,7 +578,7 @@ static void nv_pcie_gen3_enable(struct amdgpu_device *adev)
 
 static void nv_program_aspm(struct amdgpu_device *adev)
 {
-       if (!amdgpu_device_should_use_aspm(adev))
+       if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())
                return;
 
        if (!(adev->flags & AMD_IS_APU) &&
index 12ef782..ceab878 100644 (file)
 #include "mxgpu_vi.h"
 #include "amdgpu_dm.h"
 
-#if IS_ENABLED(CONFIG_X86)
-#include <asm/intel-family.h>
-#endif
-
 #define ixPCIE_LC_L1_PM_SUBSTATE       0x100100C6
 #define PCIE_LC_L1_PM_SUBSTATE__LC_L1_SUBSTATES_OVERRIDE_EN_MASK       0x00000001L
 #define PCIE_LC_L1_PM_SUBSTATE__LC_PCI_PM_L1_2_OVERRIDE_MASK   0x00000002L
@@ -1138,24 +1134,13 @@ static void vi_enable_aspm(struct amdgpu_device *adev)
                WREG32_PCIE(ixPCIE_LC_CNTL, data);
 }
 
-static bool aspm_support_quirk_check(void)
-{
-#if IS_ENABLED(CONFIG_X86)
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE);
-#else
-       return true;
-#endif
-}
-
 static void vi_program_aspm(struct amdgpu_device *adev)
 {
        u32 data, data1, orig;
        bool bL1SS = false;
        bool bClkReqSupport = true;
 
-       if (!amdgpu_device_should_use_aspm(adev) || !aspm_support_quirk_check())
+       if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())
                return;
 
        if (adev->flags & AMD_IS_APU ||
index 32abbaf..a01fd41 100644 (file)
@@ -7244,7 +7244,6 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        if (!aconnector->mst_root)
                drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
 
-       /* This defaults to the max in the range, but we want 8bpc for non-edp. */
        aconnector->base.state->max_bpc = 16;
        aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc;
 
index e4472c6..3fb4bcc 100644 (file)
@@ -271,8 +271,7 @@ static void dccg32_set_dpstreamclk(
        dccg32_set_dtbclk_p_src(dccg, src, otg_inst);
 
        /* enabled to select one of the DTBCLKs for pipe */
-       switch (otg_inst)
-       {
+       switch (dp_hpo_inst) {
        case 0:
                REG_UPDATE_2(DPSTREAMCLK_CNTL,
                             DPSTREAMCLK0_EN,
index d024007..4b7abb4 100644 (file)
@@ -2186,6 +2186,7 @@ static bool dcn32_resource_construct(
        dc->caps.edp_dsc_support = true;
        dc->caps.extended_aux_timeout_support = true;
        dc->caps.dmcub_support = true;
+       dc->caps.seamless_odm = true;
 
        /* Color pipeline capabilities */
        dc->caps.color.dpp.dcn_arch = 1;
index 2019a81..b40bace 100644 (file)
@@ -676,8 +676,8 @@ static int lt8912_parse_dt(struct lt8912 *lt)
 
        lt->hdmi_port = of_drm_find_bridge(port_node);
        if (!lt->hdmi_port) {
-               dev_err(lt->dev, "%s: Failed to get hdmi port\n", __func__);
-               ret = -ENODEV;
+               ret = -EPROBE_DEFER;
+               dev_err_probe(lt->dev, ret, "%s: Failed to get hdmi port\n", __func__);
                goto err_free_host_node;
        }
 
index 5522d61..b1a38e6 100644 (file)
@@ -328,10 +328,17 @@ static const struct dmi_system_id orientation_data[] = {
                  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
                },
                .driver_data = (void *)&lcd1200x1920_rightside_up,
-       }, {    /* Lenovo Yoga Book X90F / X91F / X91L */
+       }, {    /* Lenovo Yoga Book X90F / X90L */
                .matches = {
-                 /* Non exact match to match all versions */
-                 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
+                 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+               },
+               .driver_data = (void *)&lcd1200x1920_rightside_up,
+       }, {    /* Lenovo Yoga Book X91F / X91L */
+               .matches = {
+                 /* Non exact match to match F + L versions */
+                 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
                },
                .driver_data = (void *)&lcd1200x1920_rightside_up,
        }, {    /* Lenovo Yoga Tablet 2 830F / 830L */
index 82be0fb..d5b5d40 100644 (file)
@@ -683,6 +683,14 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
         */
        intel_vrr_send_push(new_crtc_state);
 
+       /*
+        * Seamless M/N update may need to update frame timings.
+        *
+        * FIXME Should be synchronized with the start of vblank somehow...
+        */
+       if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
+               intel_crtc_update_active_timings(new_crtc_state);
+
        local_irq_enable();
 
        if (intel_vgpu_active(dev_priv))
index d3994e2..208b1b5 100644 (file)
@@ -5145,6 +5145,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
         * only fields that are know to not cause problems are preserved. */
 
        saved_state->uapi = crtc_state->uapi;
+       saved_state->inherited = crtc_state->inherited;
        saved_state->scaler_state = crtc_state->scaler_state;
        saved_state->shared_dpll = crtc_state->shared_dpll;
        saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
index 257aa2b..3485d5e 100644 (file)
@@ -384,15 +384,12 @@ static void disable_all_event_handlers(struct drm_i915_private *i915)
        }
 }
 
-static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
+static void adlp_pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
 {
        enum pipe pipe;
 
-       if (DISPLAY_VER(i915) < 13)
-               return;
-
        /*
-        * Wa_16015201720:adl-p,dg2, mtl
+        * Wa_16015201720:adl-p,dg2
         * The WA requires clock gating to be disabled all the time
         * for pipe A and B.
         * For pipe C and D clock gating needs to be disabled only
@@ -408,6 +405,25 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
                                     PIPEDMC_GATING_DIS, 0);
 }
 
+static void mtl_pipedmc_clock_gating_wa(struct drm_i915_private *i915)
+{
+       /*
+        * Wa_16015201720
+        * The WA requires clock gating to be disabled all the time
+        * for pipe A and B.
+        */
+       intel_de_rmw(i915, GEN9_CLKGATE_DIS_0, 0,
+                    MTL_PIPEDMC_GATING_DIS_A | MTL_PIPEDMC_GATING_DIS_B);
+}
+
+static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
+{
+       if (DISPLAY_VER(i915) >= 14 && enable)
+               mtl_pipedmc_clock_gating_wa(i915);
+       else if (DISPLAY_VER(i915) == 13)
+               adlp_pipedmc_clock_gating_wa(i915, enable);
+}
+
 void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe)
 {
        if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe)))
index f76b062..38825b3 100644 (file)
@@ -210,6 +210,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
        bool prealloc = false;
        void __iomem *vaddr;
        struct drm_i915_gem_object *obj;
+       struct i915_gem_ww_ctx ww;
        int ret;
 
        mutex_lock(&ifbdev->hpd_lock);
@@ -283,13 +284,24 @@ static int intelfb_create(struct drm_fb_helper *helper,
                info->fix.smem_len = vma->size;
        }
 
-       vaddr = i915_vma_pin_iomap(vma);
-       if (IS_ERR(vaddr)) {
-               drm_err(&dev_priv->drm,
-                       "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
-               ret = PTR_ERR(vaddr);
-               goto out_unpin;
+       for_i915_gem_ww(&ww, ret, false) {
+               ret = i915_gem_object_lock(vma->obj, &ww);
+
+               if (ret)
+                       continue;
+
+               vaddr = i915_vma_pin_iomap(vma);
+               if (IS_ERR(vaddr)) {
+                       drm_err(&dev_priv->drm,
+                               "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
+                       ret = PTR_ERR(vaddr);
+                       continue;
+               }
        }
+
+       if (ret)
+               goto out_unpin;
+
        info->screen_base = vaddr;
        info->screen_size = vma->size;
 
index f0dbfc4..40d357c 100644 (file)
@@ -737,12 +737,12 @@ int intel_gt_init(struct intel_gt *gt)
        if (err)
                goto err_gt;
 
-       intel_uc_init_late(&gt->uc);
-
        err = i915_inject_probe_error(gt->i915, -EIO);
        if (err)
                goto err_gt;
 
+       intel_uc_init_late(&gt->uc);
+
        intel_migrate_init(&gt->migrate, gt);
 
        goto out_fw;
index cef3d6f..56b993f 100644 (file)
 #include "intel_rc6.h"
 #include "intel_rps.h"
 #include "intel_wakeref.h"
-#include "intel_pcode.h"
 #include "pxp/intel_pxp_pm.h"
 
 #define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2)
 
-static void mtl_media_busy(struct intel_gt *gt)
-{
-       /* Wa_14017073508: mtl */
-       if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
-           gt->type == GT_MEDIA)
-               snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE,
-                                 PCODE_MBOX_GT_STATE_MEDIA_BUSY,
-                                 PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0);
-}
-
-static void mtl_media_idle(struct intel_gt *gt)
-{
-       /* Wa_14017073508: mtl */
-       if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
-           gt->type == GT_MEDIA)
-               snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE,
-                                 PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY,
-                                 PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0);
-}
-
 static void user_forcewake(struct intel_gt *gt, bool suspend)
 {
        int count = atomic_read(&gt->user_wakeref);
@@ -93,9 +72,6 @@ static int __gt_unpark(struct intel_wakeref *wf)
 
        GT_TRACE(gt, "\n");
 
-       /* Wa_14017073508: mtl */
-       mtl_media_busy(gt);
-
        /*
         * It seems that the DMC likes to transition between the DC states a lot
         * when there are no connected displays (no active power domains) during
@@ -145,9 +121,6 @@ static int __gt_park(struct intel_wakeref *wf)
        GEM_BUG_ON(!wakeref);
        intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
 
-       /* Wa_14017073508: mtl */
-       mtl_media_idle(gt);
-
        return 0;
 }
 
index 83df4cd..80dbbef 100644 (file)
@@ -580,7 +580,7 @@ static bool perf_limit_reasons_eval(void *data)
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(perf_limit_reasons_fops, perf_limit_reasons_get,
-                       perf_limit_reasons_clear, "%llu\n");
+                       perf_limit_reasons_clear, "0x%llx\n");
 
 void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root)
 {
index 5c91622..f4150f6 100644 (file)
@@ -486,6 +486,7 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6)
 static bool rc6_supported(struct intel_rc6 *rc6)
 {
        struct drm_i915_private *i915 = rc6_to_i915(rc6);
+       struct intel_gt *gt = rc6_to_gt(rc6);
 
        if (!HAS_RC6(i915))
                return false;
@@ -502,6 +503,13 @@ static bool rc6_supported(struct intel_rc6 *rc6)
                return false;
        }
 
+       if (IS_MTL_MEDIA_STEP(gt->i915, STEP_A0, STEP_B0) &&
+           gt->type == GT_MEDIA) {
+               drm_notice(&i915->drm,
+                          "Media RC6 disabled on A step\n");
+               return false;
+       }
+
        return true;
 }
 
index fc3b994..710999d 100644 (file)
@@ -1571,6 +1571,27 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf,
 
 #endif //CONFIG_DRM_I915_CAPTURE_ERROR
 
+static void guc_capture_find_ecode(struct intel_engine_coredump *ee)
+{
+       struct gcap_reg_list_info *reginfo;
+       struct guc_mmio_reg *regs;
+       i915_reg_t reg_ipehr = RING_IPEHR(0);
+       i915_reg_t reg_instdone = RING_INSTDONE(0);
+       int i;
+
+       if (!ee->guc_capture_node)
+               return;
+
+       reginfo = ee->guc_capture_node->reginfo + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE;
+       regs = reginfo->regs;
+       for (i = 0; i < reginfo->num_regs; i++) {
+               if (regs[i].offset == reg_ipehr.reg)
+                       ee->ipehr = regs[i].value;
+               else if (regs[i].offset == reg_instdone.reg)
+                       ee->instdone.instdone = regs[i].value;
+       }
+}
+
 void intel_guc_capture_free_node(struct intel_engine_coredump *ee)
 {
        if (!ee || !ee->guc_capture_node)
@@ -1612,6 +1633,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt,
                        list_del(&n->link);
                        ee->guc_capture_node = n;
                        ee->guc_capture = guc->capture;
+                       guc_capture_find_ecode(ee);
                        return;
                }
        }
index b585509..8f8dd05 100644 (file)
 
 static bool __guc_rc_supported(struct intel_guc *guc)
 {
-       struct intel_gt *gt = guc_to_gt(guc);
-
-       /*
-        * Wa_14017073508: mtl
-        * Do not enable gucrc to avoid additional interrupts which
-        * may disrupt pcode wa.
-        */
-       if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
-           gt->type == GT_MEDIA)
-               return false;
-
        /* GuC RC is unavailable for pre-Gen12 */
        return guc->submission_supported &&
-               GRAPHICS_VER(gt->i915) >= 12;
+               GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
 }
 
 static bool __guc_rc_selected(struct intel_guc *guc)
index a9fea11..8ef9388 100644 (file)
@@ -92,8 +92,7 @@ static void debug_active_init(struct i915_active *ref)
 static void debug_active_activate(struct i915_active *ref)
 {
        lockdep_assert_held(&ref->tree_lock);
-       if (!atomic_read(&ref->count)) /* before the first inc */
-               debug_object_activate(ref, &active_debug_desc);
+       debug_object_activate(ref, &active_debug_desc);
 }
 
 static void debug_active_deactivate(struct i915_active *ref)
index 4683a5b..1225bc4 100644 (file)
@@ -687,11 +687,6 @@ hwm_get_preregistration_info(struct drm_i915_private *i915)
                for_each_gt(gt, i915, i)
                        hwm_energy(&hwmon->ddat_gt[i], &energy);
        }
-
-       /* Enable PL1 power limit */
-       if (i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit))
-               hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
-                                                   PKG_PWR_LIM_1_EN, PKG_PWR_LIM_1_EN);
 }
 
 void i915_hwmon_register(struct drm_i915_private *i915)
index 3b26423..747b53b 100644 (file)
  * GEN9 clock gating regs
  */
 #define GEN9_CLKGATE_DIS_0             _MMIO(0x46530)
-#define   DARBF_GATING_DIS             (1 << 27)
-#define   PWM2_GATING_DIS              (1 << 14)
-#define   PWM1_GATING_DIS              (1 << 13)
+#define   DARBF_GATING_DIS             REG_BIT(27)
+#define   MTL_PIPEDMC_GATING_DIS_A     REG_BIT(15)
+#define   MTL_PIPEDMC_GATING_DIS_B     REG_BIT(14)
+#define   PWM2_GATING_DIS              REG_BIT(14)
+#define   PWM1_GATING_DIS              REG_BIT(13)
 
 #define GEN9_CLKGATE_DIS_3             _MMIO(0x46538)
 #define   TGL_VRH_GATING_DIS           REG_BIT(31)
 /*   XEHP_PCODE_FREQUENCY_CONFIG param2 */
 #define     PCODE_MBOX_DOMAIN_NONE             0x0
 #define     PCODE_MBOX_DOMAIN_MEDIAFF          0x3
-
-/* Wa_14017210380: mtl */
-#define   PCODE_MBOX_GT_STATE                  0x50
-/* sub-commands (param1) */
-#define     PCODE_MBOX_GT_STATE_MEDIA_BUSY     0x1
-#define     PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY 0x2
-/* param2 */
-#define     PCODE_MBOX_GT_STATE_DOMAIN_MEDIA   0x1
-
 #define GEN6_PCODE_DATA                                _MMIO(0x138128)
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT       8
 #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT     16
index 79bfe39..7caf937 100644 (file)
@@ -325,23 +325,23 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
 
        ret = meson_encoder_hdmi_init(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = meson_plane_create(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = meson_overlay_create(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = meson_crtc_create(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        drm_mode_config_reset(drm);
 
@@ -359,6 +359,9 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
 
 uninstall_irq:
        free_irq(priv->vsync_irq, drm);
+unbind_all:
+       if (has_components)
+               component_unbind_all(drm->dev, drm);
 exit_afbcd:
        if (priv->afbcd.ops)
                priv->afbcd.ops->exit(priv);
index 4872d18..aae2efe 100644 (file)
@@ -487,7 +487,6 @@ static int host1x_get_resets(struct host1x *host)
 static int host1x_probe(struct platform_device *pdev)
 {
        struct host1x *host;
-       int syncpt_irq;
        int err;
 
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
@@ -517,8 +516,8 @@ static int host1x_probe(struct platform_device *pdev)
        }
 
        host->syncpt_irq = platform_get_irq(pdev, 0);
-       if (syncpt_irq < 0)
-               return syncpt_irq;
+       if (host->syncpt_irq < 0)
+               return host->syncpt_irq;
 
        mutex_init(&host->devices_lock);
        INIT_LIST_HEAD(&host->devices);
index 33edb5c..d193ed3 100644 (file)
@@ -757,6 +757,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
        struct hwmon_device *hwdev;
        const char *label;
        struct device *hdev;
+       struct device *tdev = dev;
        int i, err, id;
 
        /* Complain about invalid characters in hwmon name attribute */
@@ -826,7 +827,9 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
        hwdev->name = name;
        hdev->class = &hwmon_class;
        hdev->parent = dev;
-       hdev->of_node = dev ? dev->of_node : NULL;
+       while (tdev && !tdev->of_node)
+               tdev = tdev->parent;
+       hdev->of_node = tdev ? tdev->of_node : NULL;
        hwdev->chip = chip;
        dev_set_drvdata(hdev, drvdata);
        dev_set_name(hdev, HWMON_ID_FORMAT, id);
@@ -838,7 +841,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
 
        INIT_LIST_HEAD(&hwdev->tzdata);
 
-       if (dev && dev->of_node && chip && chip->ops->read &&
+       if (hdev->of_node && chip && chip->ops->read &&
            chip->info[0]->type == hwmon_chip &&
            (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
                err = hwmon_thermal_register_sensors(hdev);
index 66f7cea..e9614eb 100644 (file)
@@ -515,6 +515,8 @@ static const struct it87_devices it87_devices[] = {
 #define has_six_temp(data)     ((data)->features & FEAT_SIX_TEMP)
 #define has_vin3_5v(data)      ((data)->features & FEAT_VIN3_5V)
 #define has_conf_noexit(data)  ((data)->features & FEAT_CONF_NOEXIT)
+#define has_scaling(data)      ((data)->features & (FEAT_12MV_ADC | \
+                                                    FEAT_10_9MV_ADC))
 
 struct it87_sio_data {
        int sioaddr;
@@ -3134,7 +3136,7 @@ static int it87_probe(struct platform_device *pdev)
                         "Detected broken BIOS defaults, disabling PWM interface\n");
 
        /* Starting with IT8721F, we handle scaling of internal voltages */
-       if (has_12mv_adc(data)) {
+       if (has_scaling(data)) {
                if (sio_data->internal & BIT(0))
                        data->in_scaled |= BIT(3);      /* in3 is AVCC */
                if (sio_data->internal & BIT(1))
index 30850a4..87d56f0 100644 (file)
@@ -537,6 +537,12 @@ static const struct cpu_info cpu_hsx = {
        .thermal_margin_to_millidegree = &dts_eight_dot_eight_to_millidegree,
 };
 
+static const struct cpu_info cpu_skx = {
+       .reg            = &resolved_cores_reg_hsx,
+       .min_peci_revision = 0x33,
+       .thermal_margin_to_millidegree = &dts_ten_dot_six_to_millidegree,
+};
+
 static const struct cpu_info cpu_icx = {
        .reg            = &resolved_cores_reg_icx,
        .min_peci_revision = 0x40,
@@ -558,7 +564,7 @@ static const struct auxiliary_device_id peci_cputemp_ids[] = {
        },
        {
                .name = "peci_cpu.cputemp.skx",
-               .driver_data = (kernel_ulong_t)&cpu_hsx,
+               .driver_data = (kernel_ulong_t)&cpu_skx,
        },
        {
                .name = "peci_cpu.cputemp.icx",
index d1abea4..78d9f52 100644 (file)
@@ -698,14 +698,14 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                ctx->comm_base_addr = pcc_chan->shmem_base_addr;
                if (ctx->comm_base_addr) {
                        if (version == XGENE_HWMON_V2)
-                               ctx->pcc_comm_addr = (void __force *)ioremap(
-                                                       ctx->comm_base_addr,
-                                                       pcc_chan->shmem_size);
+                               ctx->pcc_comm_addr = (void __force *)devm_ioremap(&pdev->dev,
+                                                                 ctx->comm_base_addr,
+                                                                 pcc_chan->shmem_size);
                        else
-                               ctx->pcc_comm_addr = memremap(
-                                                       ctx->comm_base_addr,
-                                                       pcc_chan->shmem_size,
-                                                       MEMREMAP_WB);
+                               ctx->pcc_comm_addr = devm_memremap(&pdev->dev,
+                                                                  ctx->comm_base_addr,
+                                                                  pcc_chan->shmem_size,
+                                                                  MEMREMAP_WB);
                } else {
                        dev_err(&pdev->dev, "Failed to get PCC comm region\n");
                        rc = -ENODEV;
index 8c6c707..e067671 100644 (file)
@@ -316,6 +316,13 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
                    max_write == 0)
                        break;
        }
+
+       /*
+        * Disable the TX_EMPTY interrupt after finishing all the messages to
+        * avoid overwhelming the CPU.
+        */
+       if (ctlr->msg_tx_idx == ctlr->msg_num)
+               hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY);
 }
 
 static irqreturn_t hisi_i2c_irq(int irq, void *context)
@@ -341,7 +348,11 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
                hisi_i2c_read_rx_fifo(ctlr);
 
 out:
-       if (int_stat & HISI_I2C_INT_TRANS_CPLT || ctlr->xfer_err) {
+       /*
+        * Only use TRANS_CPLT to indicate the completion. On error cases we'll
+        * get two interrupts, INT_ERR first then TRANS_CPLT.
+        */
+       if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
                hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
                hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
                complete(ctlr->completion);
index 188f2a3..a49b14d 100644 (file)
@@ -463,6 +463,8 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
                if (num == 1 && msgs[0].len == 0)
                        goto stop;
 
+               lpi2c_imx->rx_buf = NULL;
+               lpi2c_imx->tx_buf = NULL;
                lpi2c_imx->delivered = 0;
                lpi2c_imx->msglen = msgs[i].len;
                init_completion(&lpi2c_imx->complete);
@@ -503,10 +505,14 @@ disable:
 static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
 {
        struct lpi2c_imx_struct *lpi2c_imx = dev_id;
+       unsigned int enabled;
        unsigned int temp;
 
+       enabled = readl(lpi2c_imx->base + LPI2C_MIER);
+
        lpi2c_imx_intctrl(lpi2c_imx, 0);
        temp = readl(lpi2c_imx->base + LPI2C_MSR);
+       temp &= enabled;
 
        if (temp & MSR_RDF)
                lpi2c_imx_read_rxfifo(lpi2c_imx);
index d113bed..e0f3b35 100644 (file)
@@ -171,7 +171,7 @@ static void mxs_i2c_dma_irq_callback(void *param)
 }
 
 static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
-                       struct i2c_msg *msg, uint32_t flags)
+                       struct i2c_msg *msg, u8 *buf, uint32_t flags)
 {
        struct dma_async_tx_descriptor *desc;
        struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
@@ -226,7 +226,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                }
 
                /* Queue the DMA data transfer. */
-               sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
+               sg_init_one(&i2c->sg_io[1], buf, msg->len);
                dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
                                        DMA_DEV_TO_MEM,
@@ -259,7 +259,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                /* Queue the DMA data transfer. */
                sg_init_table(i2c->sg_io, 2);
                sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
-               sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
+               sg_set_buf(&i2c->sg_io[1], buf, msg->len);
                dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
                                        DMA_MEM_TO_DEV,
@@ -563,6 +563,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
        int ret;
        int flags;
+       u8 *dma_buf;
        int use_pio = 0;
        unsigned long time_left;
 
@@ -588,13 +589,20 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
                if (ret && (ret != -ENXIO))
                        mxs_i2c_reset(i2c);
        } else {
+               dma_buf = i2c_get_dma_safe_msg_buf(msg, 1);
+               if (!dma_buf)
+                       return -ENOMEM;
+
                reinit_completion(&i2c->cmd_complete);
-               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
-               if (ret)
+               ret = mxs_i2c_dma_setup_xfer(adap, msg, dma_buf, flags);
+               if (ret) {
+                       i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
                        return ret;
+               }
 
                time_left = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
+               i2c_put_dma_safe_msg_buf(dma_buf, msg, true);
                if (!time_left)
                        goto timeout;
 
index 63259b3..3538d36 100644 (file)
@@ -308,6 +308,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip,
        u32 msg[3];
        int rc;
 
+       if (writelen > I2C_SMBUS_BLOCK_MAX)
+               return -EINVAL;
+
        memcpy(ctx->dma_buffer, data, writelen);
        paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
                               DMA_TO_DEVICE);
index 7dc990e..09e422d 100644 (file)
@@ -7,6 +7,7 @@ config IRQCHIP
 
 config ARM_GIC
        bool
+       depends on OF
        select IRQ_DOMAIN_HIERARCHY
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
@@ -35,6 +36,7 @@ config ARM_GIC_V3
        select IRQ_DOMAIN_HIERARCHY
        select PARTITION_PERCPU
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
+       select HAVE_ARM_SMCCC_DISCOVERY
 
 config ARM_GIC_V3_ITS
        bool
@@ -535,6 +537,7 @@ config TI_PRUSS_INTC
 config RISCV_INTC
        bool
        depends on RISCV
+       select IRQ_DOMAIN_HIERARCHY
 
 config SIFIVE_PLIC
        bool
index 586271b..fa4641a 100644 (file)
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING          (1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375      (1ULL << 1)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_23144      (1ULL << 2)
+#define ITS_FLAGS_FORCE_NON_SHAREABLE          (1ULL << 3)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING    (1 << 0)
 #define RDIST_FLAGS_RD_TABLES_PREALLOCATED     (1 << 1)
+#define RDIST_FLAGS_FORCE_NON_SHAREABLE                (1 << 2)
 
 #define RD_LOCAL_LPI_ENABLED                    BIT(0)
 #define RD_LOCAL_PENDTABLE_PREALLOCATED         BIT(1)
@@ -2359,6 +2361,9 @@ retry_baser:
        its_write_baser(its, baser, val);
        tmp = baser->val;
 
+       if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GITS_BASER_SHAREABILITY_MASK;
+
        if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
                /*
                 * Shareability didn't stick. Just use
@@ -3096,6 +3101,9 @@ static void its_cpu_init_lpis(void)
        gicr_write_propbaser(val, rbase + GICR_PROPBASER);
        tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
 
+       if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
+
        if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
                if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
                        /*
@@ -3120,6 +3128,9 @@ static void its_cpu_init_lpis(void)
        gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
        tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
 
+       if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
+
        if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
                /*
                 * The HW reports non-shareable, we must remove the
@@ -4710,6 +4721,19 @@ static bool __maybe_unused its_enable_quirk_hip07_161600802(void *data)
        return true;
 }
 
+static bool __maybe_unused its_enable_rk3588001(void *data)
+{
+       struct its_node *its = data;
+
+       if (!of_machine_is_compatible("rockchip,rk3588"))
+               return false;
+
+       its->flags |= ITS_FLAGS_FORCE_NON_SHAREABLE;
+       gic_rdists->flags |= RDIST_FLAGS_FORCE_NON_SHAREABLE;
+
+       return true;
+}
+
 static const struct gic_quirk its_quirks[] = {
 #ifdef CONFIG_CAVIUM_ERRATUM_22375
        {
@@ -4756,6 +4780,14 @@ static const struct gic_quirk its_quirks[] = {
                .init   = its_enable_quirk_hip07_161600802,
        },
 #endif
+#ifdef CONFIG_ROCKCHIP_ERRATUM_3588001
+       {
+               .desc   = "ITS: Rockchip erratum RK3588001",
+               .iidr   = 0x0201743b,
+               .mask   = 0xffffffff,
+               .init   = its_enable_rk3588001,
+       },
+#endif
        {
        }
 };
@@ -5096,6 +5128,9 @@ static int __init its_probe_one(struct resource *res,
        gits_write_cbaser(baser, its->base + GITS_CBASER);
        tmp = gits_read_cbaser(its->base + GITS_CBASER);
 
+       if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GITS_CBASER_SHAREABILITY_MASK;
+
        if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
                if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
                        /*
index fd134e1..6fcee22 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/irqchip/arm-gic-common.h>
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/irqchip/irq-partition-percpu.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/arm-smccc.h>
 
 #include <asm/cputype.h>
 #include <asm/exception.h>
@@ -47,6 +50,7 @@ struct redist_region {
 
 struct gic_chip_data {
        struct fwnode_handle    *fwnode;
+       phys_addr_t             dist_phys_base;
        void __iomem            *dist_base;
        struct redist_region    *redist_regions;
        struct rdists           rdists;
@@ -59,6 +63,10 @@ struct gic_chip_data {
        struct partition_desc   **ppi_descs;
 };
 
+#define T241_CHIPS_MAX         4
+static void __iomem *t241_dist_base_alias[T241_CHIPS_MAX] __read_mostly;
+static DEFINE_STATIC_KEY_FALSE(gic_nvidia_t241_erratum);
+
 static struct gic_chip_data gic_data __read_mostly;
 static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
 
@@ -179,6 +187,39 @@ static inline bool gic_irq_in_rdist(struct irq_data *d)
        }
 }
 
+static inline void __iomem *gic_dist_base_alias(struct irq_data *d)
+{
+       if (static_branch_unlikely(&gic_nvidia_t241_erratum)) {
+               irq_hw_number_t hwirq = irqd_to_hwirq(d);
+               u32 chip;
+
+               /*
+                * For the erratum T241-FABRIC-4, read accesses to GICD_In{E}
+                * registers are directed to the chip that owns the SPI. The
+                * the alias region can also be used for writes to the
+                * GICD_In{E} except GICD_ICENABLERn. Each chip has support
+                * for 320 {E}SPIs. Mappings for all 4 chips:
+                *    Chip0 = 32-351
+                *    Chip1 = 352-671
+                *    Chip2 = 672-991
+                *    Chip3 = 4096-4415
+                */
+               switch (__get_intid_range(hwirq)) {
+               case SPI_RANGE:
+                       chip = (hwirq - 32) / 320;
+                       break;
+               case ESPI_RANGE:
+                       chip = 3;
+                       break;
+               default:
+                       unreachable();
+               }
+               return t241_dist_base_alias[chip];
+       }
+
+       return gic_data.dist_base;
+}
+
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
        switch (get_intid_range(d)) {
@@ -337,7 +378,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
        if (gic_irq_in_rdist(d))
                base = gic_data_rdist_sgi_base();
        else
-               base = gic_data.dist_base;
+               base = gic_dist_base_alias(d);
 
        return !!(readl_relaxed(base + offset + (index / 32) * 4) & mask);
 }
@@ -588,7 +629,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
        if (gic_irq_in_rdist(d))
                base = gic_data_rdist_sgi_base();
        else
-               base = gic_data.dist_base;
+               base = gic_dist_base_alias(d);
 
        offset = convert_offset_index(d, GICD_ICFGR, &index);
 
@@ -1708,6 +1749,43 @@ static bool gic_enable_quirk_hip06_07(void *data)
        return false;
 }
 
+#define T241_CHIPN_MASK                GENMASK_ULL(45, 44)
+#define T241_CHIP_GICDA_OFFSET 0x1580000
+#define SMCCC_SOC_ID_T241      0x036b0241
+
+static bool gic_enable_quirk_nvidia_t241(void *data)
+{
+       s32 soc_id = arm_smccc_get_soc_id_version();
+       unsigned long chip_bmask = 0;
+       phys_addr_t phys;
+       u32 i;
+
+       /* Check JEP106 code for NVIDIA T241 chip (036b:0241) */
+       if ((soc_id < 0) || (soc_id != SMCCC_SOC_ID_T241))
+               return false;
+
+       /* Find the chips based on GICR regions PHYS addr */
+       for (i = 0; i < gic_data.nr_redist_regions; i++) {
+               chip_bmask |= BIT(FIELD_GET(T241_CHIPN_MASK,
+                                 (u64)gic_data.redist_regions[i].phys_base));
+       }
+
+       if (hweight32(chip_bmask) < 3)
+               return false;
+
+       /* Setup GICD alias regions */
+       for (i = 0; i < ARRAY_SIZE(t241_dist_base_alias); i++) {
+               if (chip_bmask & BIT(i)) {
+                       phys = gic_data.dist_phys_base + T241_CHIP_GICDA_OFFSET;
+                       phys |= FIELD_PREP(T241_CHIPN_MASK, i);
+                       t241_dist_base_alias[i] = ioremap(phys, SZ_64K);
+                       WARN_ON_ONCE(!t241_dist_base_alias[i]);
+               }
+       }
+       static_branch_enable(&gic_nvidia_t241_erratum);
+       return true;
+}
+
 static const struct gic_quirk gic_quirks[] = {
        {
                .desc   = "GICv3: Qualcomm MSM8996 broken firmware",
@@ -1740,6 +1818,12 @@ static const struct gic_quirk gic_quirks[] = {
                .init   = gic_enable_quirk_cavium_38539,
        },
        {
+               .desc   = "GICv3: NVIDIA erratum T241-FABRIC-4",
+               .iidr   = 0x0402043b,
+               .mask   = 0xffffffff,
+               .init   = gic_enable_quirk_nvidia_t241,
+       },
+       {
        }
 };
 
@@ -1798,7 +1882,8 @@ static void gic_enable_nmi_support(void)
                gic_chip.flags |= IRQCHIP_SUPPORTS_NMI;
 }
 
-static int __init gic_init_bases(void __iomem *dist_base,
+static int __init gic_init_bases(phys_addr_t dist_phys_base,
+                                void __iomem *dist_base,
                                 struct redist_region *rdist_regs,
                                 u32 nr_redist_regions,
                                 u64 redist_stride,
@@ -1814,6 +1899,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
                pr_info("GIC: Using split EOI/Deactivate mode\n");
 
        gic_data.fwnode = handle;
+       gic_data.dist_phys_base = dist_phys_base;
        gic_data.dist_base = dist_base;
        gic_data.redist_regions = rdist_regs;
        gic_data.nr_redist_regions = nr_redist_regions;
@@ -1841,10 +1927,13 @@ static int __init gic_init_bases(void __iomem *dist_base,
        gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
                                                 &gic_data);
        gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
-       gic_data.rdists.has_rvpeid = true;
-       gic_data.rdists.has_vlpis = true;
-       gic_data.rdists.has_direct_lpi = true;
-       gic_data.rdists.has_vpend_valid_dirty = true;
+       if (!static_branch_unlikely(&gic_nvidia_t241_erratum)) {
+               /* Disable GICv4.x features for the erratum T241-FABRIC-4 */
+               gic_data.rdists.has_rvpeid = true;
+               gic_data.rdists.has_vlpis = true;
+               gic_data.rdists.has_direct_lpi = true;
+               gic_data.rdists.has_vpend_valid_dirty = true;
+       }
 
        if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
                err = -ENOMEM;
@@ -2050,6 +2139,7 @@ static void __iomem *gic_of_iomap(struct device_node *node, int idx,
 
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
+       phys_addr_t dist_phys_base;
        void __iomem *dist_base;
        struct redist_region *rdist_regs;
        struct resource res;
@@ -2063,6 +2153,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
                return PTR_ERR(dist_base);
        }
 
+       dist_phys_base = res.start;
+
        err = gic_validate_dist_version(dist_base);
        if (err) {
                pr_err("%pOF: no distributor detected, giving up\n", node);
@@ -2094,8 +2186,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 
        gic_enable_of_quirks(node, gic_quirks, &gic_data);
 
-       err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
-                            redist_stride, &node->fwnode);
+       err = gic_init_bases(dist_phys_base, dist_base, rdist_regs,
+                            nr_redist_regions, redist_stride, &node->fwnode);
        if (err)
                goto out_unmap_rdist;
 
@@ -2411,8 +2503,9 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
                goto out_redist_unmap;
        }
 
-       err = gic_init_bases(acpi_data.dist_base, acpi_data.redist_regs,
-                            acpi_data.nr_redist_regions, 0, gsi_domain_handle);
+       err = gic_init_bases(dist->base_address, acpi_data.dist_base,
+                            acpi_data.redist_regs, acpi_data.nr_redist_regions,
+                            0, gsi_domain_handle);
        if (err)
                goto out_fwhandle_free;
 
index 95e3d2a..412196a 100644 (file)
@@ -1081,10 +1081,6 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
-static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
-{
-}
-
 static int gic_irq_domain_translate(struct irq_domain *d,
                                    struct irq_fwspec *fwspec,
                                    unsigned long *hwirq,
@@ -1167,11 +1163,6 @@ static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
        .free = irq_domain_free_irqs_top,
 };
 
-static const struct irq_domain_ops gic_irq_domain_ops = {
-       .map = gic_irq_domain_map,
-       .unmap = gic_irq_domain_unmap,
-};
-
 static int gic_init_bases(struct gic_chip_data *gic,
                          struct fwnode_handle *handle)
 {
@@ -1219,30 +1210,9 @@ static int gic_init_bases(struct gic_chip_data *gic,
                gic_irqs = 1020;
        gic->gic_irqs = gic_irqs;
 
-       if (handle) {           /* DT/ACPI */
-               gic->domain = irq_domain_create_linear(handle, gic_irqs,
-                                                      &gic_irq_domain_hierarchy_ops,
-                                                      gic);
-       } else {                /* Legacy support */
-               /*
-                * For primary GICs, skip over SGIs.
-                * No secondary GIC support whatsoever.
-                */
-               int irq_base;
-
-               gic_irqs -= 16; /* calculate # of irqs to allocate */
-
-               irq_base = irq_alloc_descs(16, 16, gic_irqs,
-                                          numa_node_id());
-               if (irq_base < 0) {
-                       WARN(1, "Cannot allocate irq_descs @ IRQ16, assuming pre-allocated\n");
-                       irq_base = 16;
-               }
-
-               gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base,
-                                                   16, &gic_irq_domain_ops, gic);
-       }
-
+       gic->domain = irq_domain_create_linear(handle, gic_irqs,
+                                              &gic_irq_domain_hierarchy_ops,
+                                              gic);
        if (WARN_ON(!gic->domain)) {
                ret = -ENODEV;
                goto error;
@@ -1297,23 +1267,6 @@ static int __init __gic_init_bases(struct gic_chip_data *gic,
        return ret;
 }
 
-void __init gic_init(void __iomem *dist_base, void __iomem *cpu_base)
-{
-       struct gic_chip_data *gic;
-
-       /*
-        * Non-DT/ACPI systems won't run a hypervisor, so let's not
-        * bother with these...
-        */
-       static_branch_disable(&supports_deactivate_key);
-
-       gic = &gic_data[0];
-       gic->raw_dist_base = dist_base;
-       gic->raw_cpu_base = cpu_base;
-
-       __gic_init_bases(gic, NULL);
-}
-
 static void gic_teardown(struct gic_chip_data *gic)
 {
        if (WARN_ON(!gic))
@@ -1325,7 +1278,6 @@ static void gic_teardown(struct gic_chip_data *gic)
                iounmap(gic->raw_cpu_base);
 }
 
-#ifdef CONFIG_OF
 static int gic_cnt __initdata;
 static bool gicv2_force_probe;
 
@@ -1570,12 +1522,6 @@ IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
 IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
 IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
-#else
-int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq)
-{
-       return -ENOTSUPP;
-}
-#endif
 
 #ifdef CONFIG_ACPI
 static struct
index d15fd38..90181c4 100644 (file)
@@ -280,9 +280,6 @@ static void acpi_set_vec_parent(int node, struct irq_domain *parent, struct acpi
 {
        int i;
 
-       if (cpu_has_flatmode)
-               node = cpu_to_node(node * CORES_PER_EIO_NODE);
-
        for (i = 0; i < MAX_IO_PICS; i++) {
                if (node == vec_group[i].node) {
                        vec_group[i].parent = parent;
@@ -343,19 +340,27 @@ static int __init pch_pic_parse_madt(union acpi_subtable_headers *header,
        if (parent)
                return pch_pic_acpi_init(parent, pchpic_entry);
 
-       return -EINVAL;
+       return 0;
 }
 
 static int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
                                        const unsigned long end)
 {
+       struct irq_domain *parent;
        struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header;
-       struct irq_domain *parent = acpi_get_vec_parent(eiointc_priv[nr_pics - 1]->node, msi_group);
+       int node;
+
+       if (cpu_has_flatmode)
+               node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE);
+       else
+               node = eiointc_priv[nr_pics - 1]->node;
+
+       parent = acpi_get_vec_parent(node, msi_group);
 
        if (parent)
                return pch_msi_acpi_init(parent, pchmsi_entry);
 
-       return -EINVAL;
+       return 0;
 }
 
 static int __init acpi_cascade_irqdomain_init(void)
@@ -379,6 +384,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
        int i, ret, parent_irq;
        unsigned long node_map;
        struct eiointc_priv *priv;
+       int node;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -416,13 +422,19 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
        parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
        irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
 
-       register_syscore_ops(&eiointc_syscore_ops);
-       cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
+       if (nr_pics == 1) {
+               register_syscore_ops(&eiointc_syscore_ops);
+               cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
                                  "irqchip/loongarch/intc:starting",
                                  eiointc_router_init, NULL);
+       }
 
-       acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group);
-       acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group);
+       if (cpu_has_flatmode)
+               node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
+       else
+               node = acpi_eiointc->node;
+       acpi_set_vec_parent(node, priv->eiointc_domain, pch_group);
+       acpi_set_vec_parent(node, priv->eiointc_domain, msi_group);
        ret = acpi_cascade_irqdomain_init();
 
        return ret;
index 437f1af..e5fe4d5 100644 (file)
@@ -311,7 +311,8 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
        pch_pic_handle[nr_pics] = domain_handle;
        pch_pic_priv[nr_pics++] = priv;
 
-       register_syscore_ops(&pch_pic_syscore_ops);
+       if (nr_pics == 1)
+               register_syscore_ops(&pch_pic_syscore_ops);
 
        return 0;
 
@@ -403,6 +404,9 @@ int __init pch_pic_acpi_init(struct irq_domain *parent,
        int ret, vec_base;
        struct fwnode_handle *domain_handle;
 
+       if (find_pch_pic(acpi_pchpic->gsi_base) >= 0)
+               return 0;
+
        vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ;
 
        domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address);
index 499e5f8..f229e3e 100644 (file)
@@ -26,20 +26,7 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
        if (unlikely(cause >= BITS_PER_LONG))
                panic("unexpected interrupt cause");
 
-       switch (cause) {
-#ifdef CONFIG_SMP
-       case RV_IRQ_SOFT:
-               /*
-                * We only use software interrupts to pass IPIs, so if a
-                * non-SMP system gets one, then we don't know what to do.
-                */
-               handle_IPI(regs);
-               break;
-#endif
-       default:
-               generic_handle_domain_irq(intc_domain, cause);
-               break;
-       }
+       generic_handle_domain_irq(intc_domain, cause);
 }
 
 /*
@@ -59,22 +46,27 @@ static void riscv_intc_irq_unmask(struct irq_data *d)
        csr_set(CSR_IE, BIT(d->hwirq));
 }
 
-static int riscv_intc_cpu_starting(unsigned int cpu)
-{
-       csr_set(CSR_IE, BIT(RV_IRQ_SOFT));
-       return 0;
-}
-
-static int riscv_intc_cpu_dying(unsigned int cpu)
+static void riscv_intc_irq_eoi(struct irq_data *d)
 {
-       csr_clear(CSR_IE, BIT(RV_IRQ_SOFT));
-       return 0;
+       /*
+        * The RISC-V INTC driver uses handle_percpu_devid_irq() flow
+        * for the per-HART local interrupts and child irqchip drivers
+        * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement
+        * chained handlers for the per-HART local interrupts.
+        *
+        * In the absence of irq_eoi(), the chained_irq_enter() and
+        * chained_irq_exit() functions (used by child irqchip drivers)
+        * will do unnecessary mask/unmask of per-HART local interrupts
+        * at the time of handling interrupts. To avoid this, we provide
+        * an empty irq_eoi() callback for RISC-V INTC irqchip.
+        */
 }
 
 static struct irq_chip riscv_intc_chip = {
        .name = "RISC-V INTC",
        .irq_mask = riscv_intc_irq_mask,
        .irq_unmask = riscv_intc_irq_unmask,
+       .irq_eoi = riscv_intc_irq_eoi,
 };
 
 static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
@@ -87,11 +79,39 @@ static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
+static int riscv_intc_domain_alloc(struct irq_domain *domain,
+                                  unsigned int virq, unsigned int nr_irqs,
+                                  void *arg)
+{
+       int i, ret;
+       irq_hw_number_t hwirq;
+       unsigned int type = IRQ_TYPE_NONE;
+       struct irq_fwspec *fwspec = arg;
+
+       ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < nr_irqs; i++) {
+               ret = riscv_intc_domain_map(domain, virq + i, hwirq + i);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static const struct irq_domain_ops riscv_intc_domain_ops = {
        .map    = riscv_intc_domain_map,
        .xlate  = irq_domain_xlate_onecell,
+       .alloc  = riscv_intc_domain_alloc
 };
 
+static struct fwnode_handle *riscv_intc_hwnode(void)
+{
+       return intc_domain->fwnode;
+}
+
 static int __init riscv_intc_init(struct device_node *node,
                                  struct device_node *parent)
 {
@@ -126,10 +146,7 @@ static int __init riscv_intc_init(struct device_node *node,
                return rc;
        }
 
-       cpuhp_setup_state(CPUHP_AP_IRQ_RISCV_STARTING,
-                         "irqchip/riscv/intc:starting",
-                         riscv_intc_cpu_starting,
-                         riscv_intc_cpu_dying);
+       riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
 
        pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
 
index 40cb171..3ba53dc 100644 (file)
@@ -72,7 +72,9 @@ struct dm_crypt_io {
        struct crypt_config *cc;
        struct bio *base_bio;
        u8 *integrity_metadata;
-       bool integrity_metadata_from_pool;
+       bool integrity_metadata_from_pool:1;
+       bool in_tasklet:1;
+
        struct work_struct work;
        struct tasklet_struct tasklet;
 
@@ -1730,6 +1732,7 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
        io->ctx.r.req = NULL;
        io->integrity_metadata = NULL;
        io->integrity_metadata_from_pool = false;
+       io->in_tasklet = false;
        atomic_set(&io->io_pending, 0);
 }
 
@@ -1776,14 +1779,13 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
         * our tasklet. In this case we need to delay bio_endio()
         * execution to after the tasklet is done and dequeued.
         */
-       if (tasklet_trylock(&io->tasklet)) {
-               tasklet_unlock(&io->tasklet);
-               bio_endio(base_bio);
+       if (io->in_tasklet) {
+               INIT_WORK(&io->work, kcryptd_io_bio_endio);
+               queue_work(cc->io_queue, &io->work);
                return;
        }
 
-       INIT_WORK(&io->work, kcryptd_io_bio_endio);
-       queue_work(cc->io_queue, &io->work);
+       bio_endio(base_bio);
 }
 
 /*
@@ -1936,6 +1938,7 @@ pop_from_list:
                        io = crypt_io_from_node(rb_first(&write_tree));
                        rb_erase(&io->rb_node, &write_tree);
                        kcryptd_io_write(io);
+                       cond_resched();
                } while (!RB_EMPTY_ROOT(&write_tree));
                blk_finish_plug(&plug);
        }
@@ -2230,6 +2233,7 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io)
                 * it is being executed with irqs disabled.
                 */
                if (in_hardirq() || irqs_disabled()) {
+                       io->in_tasklet = true;
                        tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work);
                        tasklet_schedule(&io->tasklet);
                        return;
index c21a19a..db2d997 100644 (file)
@@ -188,7 +188,7 @@ static int dm_stat_in_flight(struct dm_stat_shared *shared)
               atomic_read(&shared->in_flight[WRITE]);
 }
 
-void dm_stats_init(struct dm_stats *stats)
+int dm_stats_init(struct dm_stats *stats)
 {
        int cpu;
        struct dm_stats_last_position *last;
@@ -197,11 +197,16 @@ void dm_stats_init(struct dm_stats *stats)
        INIT_LIST_HEAD(&stats->list);
        stats->precise_timestamps = false;
        stats->last = alloc_percpu(struct dm_stats_last_position);
+       if (!stats->last)
+               return -ENOMEM;
+
        for_each_possible_cpu(cpu) {
                last = per_cpu_ptr(stats->last, cpu);
                last->last_sector = (sector_t)ULLONG_MAX;
                last->last_rw = UINT_MAX;
        }
+
+       return 0;
 }
 
 void dm_stats_cleanup(struct dm_stats *stats)
index 0bc152c..c6728c8 100644 (file)
@@ -21,7 +21,7 @@ struct dm_stats_aux {
        unsigned long long duration_ns;
 };
 
-void dm_stats_init(struct dm_stats *st);
+int dm_stats_init(struct dm_stats *st);
 void dm_stats_cleanup(struct dm_stats *st);
 
 struct mapped_device;
index 6cd105c..13d4677 100644 (file)
@@ -3369,6 +3369,7 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        pt->low_water_blocks = low_water_blocks;
        pt->adjusted_pf = pt->requested_pf = pf;
        ti->num_flush_bios = 1;
+       ti->limit_swap_bios = true;
 
        /*
         * Only need to enable discards if the pool should pass
@@ -4249,6 +4250,7 @@ static int thin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad;
 
        ti->num_flush_bios = 1;
+       ti->limit_swap_bios = true;
        ti->flush_supported = true;
        ti->accounts_remapped_io = true;
        ti->per_io_data_size = sizeof(struct dm_thin_endio_hook);
index f5cc330..2d0f934 100644 (file)
@@ -2097,7 +2097,9 @@ static struct mapped_device *alloc_dev(int minor)
        if (!md->pending_io)
                goto bad;
 
-       dm_stats_init(&md->stats);
+       r = dm_stats_init(&md->stats);
+       if (r < 0)
+               goto bad;
 
        /* Populate the mapping, nobody knows we exist yet */
        spin_lock(&_minor_lock);
index e968322..70887e0 100644 (file)
@@ -263,7 +263,7 @@ static int b53_mmap_probe_of(struct platform_device *pdev,
                if (of_property_read_u32(of_port, "reg", &reg))
                        continue;
 
-               if (reg < B53_CPU_PORT)
+               if (reg < B53_N_PORTS)
                        pdata->enabled_ports |= BIT(reg);
        }
 
index c2d81b7..02410ac 100644 (file)
@@ -396,6 +396,9 @@ mt7530_fdb_write(struct mt7530_priv *priv, u16 vid,
 /* Set up switch core clock for MT7530 */
 static void mt7530_pll_setup(struct mt7530_priv *priv)
 {
+       /* Disable core clock */
+       core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
+
        /* Disable PLL */
        core_write(priv, CORE_GSWPLL_GRP1, 0);
 
@@ -409,14 +412,19 @@ static void mt7530_pll_setup(struct mt7530_priv *priv)
                   RG_GSWPLL_EN_PRE |
                   RG_GSWPLL_POSDIV_200M(2) |
                   RG_GSWPLL_FBKDIV_200M(32));
+
+       udelay(20);
+
+       /* Enable core clock */
+       core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
 }
 
-/* Setup TX circuit including relevant PAD and driving */
+/* Setup port 6 interface mode and TRGMII TX circuit */
 static int
 mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
 {
        struct mt7530_priv *priv = ds->priv;
-       u32 ncpo1, ssc_delta, trgint, i, xtal;
+       u32 ncpo1, ssc_delta, trgint, xtal;
 
        xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
 
@@ -433,6 +441,10 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
                break;
        case PHY_INTERFACE_MODE_TRGMII:
                trgint = 1;
+               if (xtal == HWTRAP_XTAL_25MHZ)
+                       ssc_delta = 0x57;
+               else
+                       ssc_delta = 0x87;
                if (priv->id == ID_MT7621) {
                        /* PLL frequency: 150MHz: 1.2GBit */
                        if (xtal == HWTRAP_XTAL_40MHZ)
@@ -452,23 +464,12 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
                return -EINVAL;
        }
 
-       if (xtal == HWTRAP_XTAL_25MHZ)
-               ssc_delta = 0x57;
-       else
-               ssc_delta = 0x87;
-
        mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
                   P6_INTF_MODE(trgint));
 
        if (trgint) {
-               /* Lower Tx Driving for TRGMII path */
-               for (i = 0 ; i < NUM_TRGMII_CTRL ; i++)
-                       mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
-                                    TD_DM_DRVP(8) | TD_DM_DRVN(8));
-
-               /* Disable MT7530 core and TRGMII Tx clocks */
-               core_clear(priv, CORE_TRGMII_GSW_CLK_CG,
-                          REG_GSWCK_EN | REG_TRGMIICK_EN);
+               /* Disable the MT7530 TRGMII clocks */
+               core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
 
                /* Setup the MT7530 TRGMII Tx Clock */
                core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1));
@@ -485,13 +486,8 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
                           RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) |
                           RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
 
-               /* Enable MT7530 core and TRGMII Tx clocks */
-               core_set(priv, CORE_TRGMII_GSW_CLK_CG,
-                        REG_GSWCK_EN | REG_TRGMIICK_EN);
-       } else {
-               for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
-                       mt7530_rmw(priv, MT7530_TRGMII_RD(i),
-                                  RD_TAP_MASK, RD_TAP(16));
+               /* Enable the MT7530 TRGMII clocks */
+               core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
        }
 
        return 0;
@@ -2201,6 +2197,15 @@ mt7530_setup(struct dsa_switch *ds)
 
        mt7530_pll_setup(priv);
 
+       /* Lower Tx driving for TRGMII path */
+       for (i = 0; i < NUM_TRGMII_CTRL; i++)
+               mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
+                            TD_DM_DRVP(8) | TD_DM_DRVN(8));
+
+       for (i = 0; i < NUM_TRGMII_CTRL; i++)
+               mt7530_rmw(priv, MT7530_TRGMII_RD(i),
+                          RD_TAP_MASK, RD_TAP(16));
+
        /* Enable port 6 */
        val = mt7530_read(priv, MT7530_MHWTRAP);
        val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
index bca68ed..da9d4b3 100644 (file)
@@ -370,8 +370,7 @@ static const struct ethtool_rmon_hist_range enetc_rmon_ranges[] = {
 };
 
 static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
-                            struct ethtool_rmon_stats *s,
-                            const struct ethtool_rmon_hist_range **ranges)
+                            struct ethtool_rmon_stats *s)
 {
        s->undersize_pkts = enetc_port_rd(hw, ENETC_PM_RUND(mac));
        s->oversize_pkts = enetc_port_rd(hw, ENETC_PM_ROVR(mac));
@@ -393,8 +392,6 @@ static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
        s->hist_tx[4] = enetc_port_rd(hw, ENETC_PM_T1023(mac));
        s->hist_tx[5] = enetc_port_rd(hw, ENETC_PM_T1522(mac));
        s->hist_tx[6] = enetc_port_rd(hw, ENETC_PM_T1523X(mac));
-
-       *ranges = enetc_rmon_ranges;
 }
 
 static void enetc_get_eth_mac_stats(struct net_device *ndev,
@@ -447,13 +444,15 @@ static void enetc_get_rmon_stats(struct net_device *ndev,
        struct enetc_hw *hw = &priv->si->hw;
        struct enetc_si *si = priv->si;
 
+       *ranges = enetc_rmon_ranges;
+
        switch (rmon_stats->src) {
        case ETHTOOL_MAC_STATS_SRC_EMAC:
-               enetc_rmon_stats(hw, 0, rmon_stats, ranges);
+               enetc_rmon_stats(hw, 0, rmon_stats);
                break;
        case ETHTOOL_MAC_STATS_SRC_PMAC:
                if (si->hw_features & ENETC_SI_F_QBU)
-                       enetc_rmon_stats(hw, 1, rmon_stats, ranges);
+                       enetc_rmon_stats(hw, 1, rmon_stats);
                break;
        case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
                ethtool_aggregate_rmon_stats(ndev, rmon_stats);
index ce574d0..5f81470 100644 (file)
@@ -537,7 +537,10 @@ static int gve_get_link_ksettings(struct net_device *netdev,
                                  struct ethtool_link_ksettings *cmd)
 {
        struct gve_priv *priv = netdev_priv(netdev);
-       int err = gve_adminq_report_link_speed(priv);
+       int err = 0;
+
+       if (priv->link_speed == 0)
+               err = gve_adminq_report_link_speed(priv);
 
        cmd->base.speed = priv->link_speed;
        return err;
index 924f972..72b091f 100644 (file)
@@ -171,10 +171,10 @@ static char *i40e_create_dummy_packet(u8 *dummy_packet, bool ipv4, u8 l4proto,
                                      struct i40e_fdir_filter *data)
 {
        bool is_vlan = !!data->vlan_tag;
-       struct vlan_hdr vlan;
-       struct ipv6hdr ipv6;
-       struct ethhdr eth;
-       struct iphdr ip;
+       struct vlan_hdr vlan = {};
+       struct ipv6hdr ipv6 = {};
+       struct ethhdr eth = {};
+       struct iphdr ip = {};
        u8 *tmp;
 
        if (ipv4) {
index 16c4909..dd11dbb 100644 (file)
@@ -661,7 +661,7 @@ struct iavf_rx_ptype_decoded iavf_ptype_lookup[BIT(8)] = {
        /* Non Tunneled IPv6 */
        IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
        IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
-       IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY3),
+       IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY4),
        IAVF_PTT_UNUSED_ENTRY(91),
        IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP,  PAY4),
        IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
index 3273aeb..095201e 100644 (file)
@@ -893,6 +893,10 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
+       /* Do not track VLAN 0 filter, always added by the PF on VF init */
+       if (!vid)
+               return 0;
+
        if (!VLAN_FILTERING_ALLOWED(adapter))
                return -EIO;
 
@@ -919,6 +923,10 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
+       /* We do not track VLAN 0 filter */
+       if (!vid)
+               return 0;
+
        iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto)));
        if (proto == cpu_to_be16(ETH_P_8021Q))
                clear_bit(vid, adapter->vsi.active_cvlans);
@@ -5066,6 +5074,11 @@ static void iavf_remove(struct pci_dev *pdev)
                        mutex_unlock(&adapter->crit_lock);
                        break;
                }
+               /* Simply return if we already went through iavf_shutdown */
+               if (adapter->state == __IAVF_REMOVE) {
+                       mutex_unlock(&adapter->crit_lock);
+                       return;
+               }
 
                mutex_unlock(&adapter->crit_lock);
                usleep_range(500, 1000);
index 18b6a70..e989fed 100644 (file)
@@ -1096,7 +1096,7 @@ static inline void iavf_rx_hash(struct iavf_ring *ring,
                cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<
                            IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT);
 
-       if (ring->netdev->features & NETIF_F_RXHASH)
+       if (!(ring->netdev->features & NETIF_F_RXHASH))
                return;
 
        if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
index 6d23338..4e17d00 100644 (file)
@@ -2446,8 +2446,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                list_for_each_entry(f, &adapter->vlan_filter_list, list) {
                        if (f->is_new_vlan) {
                                f->is_new_vlan = false;
-                               if (!f->vlan.vid)
-                                       continue;
                                if (f->vlan.tpid == ETH_P_8021Q)
                                        set_bit(f->vlan.vid,
                                                adapter->vsi.active_cvlans);
index 0f52ea3..450317d 100644 (file)
@@ -291,6 +291,7 @@ static void ice_vsi_delete_from_hw(struct ice_vsi *vsi)
        struct ice_vsi_ctx *ctxt;
        int status;
 
+       ice_fltr_remove_all(vsi);
        ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
        if (!ctxt)
                return;
@@ -2892,7 +2893,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
            !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
                ice_cfg_sw_lldp(vsi, false, false);
 
-       ice_fltr_remove_all(vsi);
        ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
        err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
        if (err)
index c233464..0d8b8c6 100644 (file)
@@ -4641,6 +4641,12 @@ static int ice_start_eth(struct ice_vsi *vsi)
        return err;
 }
 
+static void ice_stop_eth(struct ice_vsi *vsi)
+{
+       ice_fltr_remove_all(vsi);
+       ice_vsi_close(vsi);
+}
+
 static int ice_init_eth(struct ice_pf *pf)
 {
        struct ice_vsi *vsi = ice_get_main_vsi(pf);
@@ -5129,7 +5135,7 @@ void ice_unload(struct ice_pf *pf)
 {
        ice_deinit_features(pf);
        ice_deinit_rdma(pf);
-       ice_vsi_close(ice_get_main_vsi(pf));
+       ice_stop_eth(ice_get_main_vsi(pf));
        ice_vsi_decfg(ice_get_main_vsi(pf));
        ice_deinit_dev(pf);
 }
index 96a64c2..0cc05e5 100644 (file)
@@ -1341,15 +1341,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
        struct ice_vf *vf;
        int ret;
 
+       vf = ice_get_vf_by_id(pf, vf_id);
+       if (!vf)
+               return -EINVAL;
+
        if (ice_is_eswitch_mode_switchdev(pf)) {
                dev_info(ice_pf_to_dev(pf), "Trusted VF is forbidden in switchdev mode\n");
                return -EOPNOTSUPP;
        }
 
-       vf = ice_get_vf_by_id(pf, vf_id);
-       if (!vf)
-               return -EINVAL;
-
        ret = ice_check_vf_ready_for_cfg(vf);
        if (ret)
                goto out_put_vf;
index dfd2286..b61dd9f 100644 (file)
@@ -1210,6 +1210,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
                                ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc);
                        if (++ntc == cnt)
                                ntc = 0;
+                       rx_ring->first_desc = ntc;
                        continue;
                }
 
index 03bc1e8..274c781 100644 (file)
@@ -109,6 +109,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *);
 static void igb_setup_mrqc(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
 static void igb_remove(struct pci_dev *pdev);
+static void igb_init_queue_configuration(struct igb_adapter *adapter);
 static int igb_sw_init(struct igb_adapter *);
 int igb_open(struct net_device *);
 int igb_close(struct net_device *);
@@ -175,9 +176,7 @@ static void igb_nfc_filter_restore(struct igb_adapter *adapter);
 
 #ifdef CONFIG_PCI_IOV
 static int igb_vf_configure(struct igb_adapter *adapter, int vf);
-static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs);
-static int igb_disable_sriov(struct pci_dev *dev);
-static int igb_pci_disable_sriov(struct pci_dev *dev);
+static int igb_disable_sriov(struct pci_dev *dev, bool reinit);
 #endif
 
 static int igb_suspend(struct device *);
@@ -3665,7 +3664,7 @@ err_sw_init:
        kfree(adapter->shadow_vfta);
        igb_clear_interrupt_scheme(adapter);
 #ifdef CONFIG_PCI_IOV
-       igb_disable_sriov(pdev);
+       igb_disable_sriov(pdev, false);
 #endif
        pci_iounmap(pdev, adapter->io_addr);
 err_ioremap:
@@ -3679,7 +3678,38 @@ err_dma:
 }
 
 #ifdef CONFIG_PCI_IOV
-static int igb_disable_sriov(struct pci_dev *pdev)
+static int igb_sriov_reinit(struct pci_dev *dev)
+{
+       struct net_device *netdev = pci_get_drvdata(dev);
+       struct igb_adapter *adapter = netdev_priv(netdev);
+       struct pci_dev *pdev = adapter->pdev;
+
+       rtnl_lock();
+
+       if (netif_running(netdev))
+               igb_close(netdev);
+       else
+               igb_reset(adapter);
+
+       igb_clear_interrupt_scheme(adapter);
+
+       igb_init_queue_configuration(adapter);
+
+       if (igb_init_interrupt_scheme(adapter, true)) {
+               rtnl_unlock();
+               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+               return -ENOMEM;
+       }
+
+       if (netif_running(netdev))
+               igb_open(netdev);
+
+       rtnl_unlock();
+
+       return 0;
+}
+
+static int igb_disable_sriov(struct pci_dev *pdev, bool reinit)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct igb_adapter *adapter = netdev_priv(netdev);
@@ -3713,10 +3743,10 @@ static int igb_disable_sriov(struct pci_dev *pdev)
                adapter->flags |= IGB_FLAG_DMAC;
        }
 
-       return 0;
+       return reinit ? igb_sriov_reinit(pdev) : 0;
 }
 
-static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
+static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct igb_adapter *adapter = netdev_priv(netdev);
@@ -3781,12 +3811,6 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
                        "Unable to allocate memory for VF MAC filter list\n");
        }
 
-       /* only call pci_enable_sriov() if no VFs are allocated already */
-       if (!old_vfs) {
-               err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
-               if (err)
-                       goto err_out;
-       }
        dev_info(&pdev->dev, "%d VFs allocated\n",
                 adapter->vfs_allocated_count);
        for (i = 0; i < adapter->vfs_allocated_count; i++)
@@ -3794,6 +3818,17 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
 
        /* DMA Coalescing is not supported in IOV mode. */
        adapter->flags &= ~IGB_FLAG_DMAC;
+
+       if (reinit) {
+               err = igb_sriov_reinit(pdev);
+               if (err)
+                       goto err_out;
+       }
+
+       /* only call pci_enable_sriov() if no VFs are allocated already */
+       if (!old_vfs)
+               err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
+
        goto out;
 
 err_out:
@@ -3863,9 +3898,7 @@ static void igb_remove(struct pci_dev *pdev)
        igb_release_hw_control(adapter);
 
 #ifdef CONFIG_PCI_IOV
-       rtnl_lock();
-       igb_disable_sriov(pdev);
-       rtnl_unlock();
+       igb_disable_sriov(pdev, false);
 #endif
 
        unregister_netdev(netdev);
@@ -3911,7 +3944,7 @@ static void igb_probe_vfs(struct igb_adapter *adapter)
        igb_reset_interrupt_capability(adapter);
 
        pci_sriov_set_totalvfs(pdev, 7);
-       igb_enable_sriov(pdev, max_vfs);
+       igb_enable_sriov(pdev, max_vfs, false);
 
 #endif /* CONFIG_PCI_IOV */
 }
@@ -9520,71 +9553,17 @@ static void igb_shutdown(struct pci_dev *pdev)
        }
 }
 
-#ifdef CONFIG_PCI_IOV
-static int igb_sriov_reinit(struct pci_dev *dev)
-{
-       struct net_device *netdev = pci_get_drvdata(dev);
-       struct igb_adapter *adapter = netdev_priv(netdev);
-       struct pci_dev *pdev = adapter->pdev;
-
-       rtnl_lock();
-
-       if (netif_running(netdev))
-               igb_close(netdev);
-       else
-               igb_reset(adapter);
-
-       igb_clear_interrupt_scheme(adapter);
-
-       igb_init_queue_configuration(adapter);
-
-       if (igb_init_interrupt_scheme(adapter, true)) {
-               rtnl_unlock();
-               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-               return -ENOMEM;
-       }
-
-       if (netif_running(netdev))
-               igb_open(netdev);
-
-       rtnl_unlock();
-
-       return 0;
-}
-
-static int igb_pci_disable_sriov(struct pci_dev *dev)
-{
-       int err = igb_disable_sriov(dev);
-
-       if (!err)
-               err = igb_sriov_reinit(dev);
-
-       return err;
-}
-
-static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs)
-{
-       int err = igb_enable_sriov(dev, num_vfs);
-
-       if (err)
-               goto out;
-
-       err = igb_sriov_reinit(dev);
-       if (!err)
-               return num_vfs;
-
-out:
-       return err;
-}
-
-#endif
 static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
 {
 #ifdef CONFIG_PCI_IOV
-       if (num_vfs == 0)
-               return igb_pci_disable_sriov(dev);
-       else
-               return igb_pci_enable_sriov(dev, num_vfs);
+       int err;
+
+       if (num_vfs == 0) {
+               return igb_disable_sriov(dev, true);
+       } else {
+               err = igb_enable_sriov(dev, num_vfs, true);
+               return err ? err : num_vfs;
+       }
 #endif
        return 0;
 }
index 3a32809..72cb1b5 100644 (file)
@@ -1074,7 +1074,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
                          igbvf_intr_msix_rx, 0, adapter->rx_ring->name,
                          netdev);
        if (err)
-               goto out;
+               goto free_irq_tx;
 
        adapter->rx_ring->itr_register = E1000_EITR(vector);
        adapter->rx_ring->itr_val = adapter->current_itr;
@@ -1083,10 +1083,14 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
        err = request_irq(adapter->msix_entries[vector].vector,
                          igbvf_msix_other, 0, netdev->name, netdev);
        if (err)
-               goto out;
+               goto free_irq_rx;
 
        igbvf_configure_msix(adapter);
        return 0;
+free_irq_rx:
+       free_irq(adapter->msix_entries[--vector].vector, netdev);
+free_irq_tx:
+       free_irq(adapter->msix_entries[--vector].vector, netdev);
 out:
        return err;
 }
index b8ba3f9..a47a2e3 100644 (file)
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright(c) 2009 - 2018 Intel Corporation. */
 
+#include <linux/etherdevice.h>
+
 #include "vf.h"
 
 static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
@@ -131,11 +133,16 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
                /* set our "perm_addr" based on info provided by PF */
                ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
                if (!ret_val) {
-                       if (msgbuf[0] == (E1000_VF_RESET |
-                                         E1000_VT_MSGTYPE_ACK))
+                       switch (msgbuf[0]) {
+                       case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
                                memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
-                       else
+                               break;
+                       case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
+                               eth_zero_addr(hw->mac.perm_addr);
+                               break;
+                       default:
                                ret_val = -E1000_ERR_MAC_INIT;
+                       }
                }
        }
 
index 2928a6c..25fc6c6 100644 (file)
@@ -6010,18 +6010,18 @@ static bool validate_schedule(struct igc_adapter *adapter,
                if (e->command != TC_TAPRIO_CMD_SET_GATES)
                        return false;
 
-               for (i = 0; i < adapter->num_tx_queues; i++) {
-                       if (e->gate_mask & BIT(i))
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       if (e->gate_mask & BIT(i)) {
                                queue_uses[i]++;
 
-                       /* There are limitations: A single queue cannot be
-                        * opened and closed multiple times per cycle unless the
-                        * gate stays open. Check for it.
-                        */
-                       if (queue_uses[i] > 1 &&
-                           !(prev->gate_mask & BIT(i)))
-                               return false;
-               }
+                               /* There are limitations: A single queue cannot
+                                * be opened and closed multiple times per cycle
+                                * unless the gate stays open. Check for it.
+                                */
+                               if (queue_uses[i] > 1 &&
+                                   !(prev->gate_mask & BIT(i)))
+                                       return false;
+                       }
        }
 
        return true;
index 7f8ffbf..ab126f8 100644 (file)
@@ -709,6 +709,7 @@ err_unreg_netdev:
 err_ptp_destroy:
        otx2_ptp_destroy(vf);
 err_detach_rsrc:
+       free_percpu(vf->hw.lmt_info);
        if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
                qmem_free(vf->dev, vf->dync_lmt);
        otx2_detach_resources(&vf->mbox);
@@ -762,6 +763,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
        otx2_shutdown_tc(vf);
        otx2vf_disable_mbox_intr(vf);
        otx2_detach_resources(&vf->mbox);
+       free_percpu(vf->hw.lmt_info);
        if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
                qmem_free(vf->dev, vf->dync_lmt);
        otx2vf_vfaf_mbox_destroy(vf);
index 0869d4f..4b5e459 100644 (file)
@@ -674,7 +674,7 @@ int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
 
        if (unlikely(_ctx->ring->hwtstamp_rx_filter != HWTSTAMP_FILTER_ALL))
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *timestamp = mlx4_en_get_hwtstamp(_ctx->mdev,
                                          mlx4_en_get_cqe_ts(_ctx->cqe));
@@ -686,7 +686,7 @@ int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
        struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
 
        if (unlikely(!(_ctx->dev->features & NETIF_F_RXHASH)))
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *hash = be32_to_cpu(_ctx->cqe->immed_rss_invalid);
        return 0;
index bcd6370..c5dae48 100644 (file)
@@ -162,7 +162,7 @@ static int mlx5e_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
 
        if (unlikely(!mlx5e_rx_hw_stamp(_ctx->rq->tstamp)))
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *timestamp =  mlx5e_cqe_ts_to_ns(_ctx->rq->ptp_cyc2time,
                                         _ctx->rq->clock, get_cqe_ts(_ctx->cqe));
@@ -174,7 +174,7 @@ static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
        const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
 
        if (unlikely(!(_ctx->xdp.rxq->dev->features & NETIF_F_RXHASH)))
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *hash = be32_to_cpu(_ctx->cqe->rss_hash_result);
        return 0;
index 8af5317..33b3620 100644 (file)
@@ -1412,6 +1412,7 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac
        struct mlx5e_macsec_aso *aso;
        struct mlx5_aso_wqe *aso_wqe;
        struct mlx5_aso *maso;
+       unsigned long expires;
        int err;
 
        aso = &macsec->aso;
@@ -1425,7 +1426,13 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac
        macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL);
 
        mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
-       err = mlx5_aso_poll_cq(maso, false);
+       expires = jiffies + msecs_to_jiffies(10);
+       do {
+               err = mlx5_aso_poll_cq(maso, false);
+               if (err)
+                       usleep_range(2, 10);
+       } while (err && time_is_after_jiffies(expires));
+
        if (err)
                goto err_out;
 
index 2449731..89de92d 100644 (file)
@@ -117,12 +117,14 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
        if (!MLX5_CAP_GEN(priv->mdev, ets))
                return -EOPNOTSUPP;
 
-       ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
-       for (i = 0; i < ets->ets_cap; i++) {
+       for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
                err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
                if (err)
                        return err;
+       }
 
+       ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+       for (i = 0; i < ets->ets_cap; i++) {
                err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
                if (err)
                        return err;
index a7f2ab2..7ca7e9b 100644 (file)
@@ -4150,8 +4150,12 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
                }
        }
 
-       if (mlx5e_is_uplink_rep(priv))
+       if (mlx5e_is_uplink_rep(priv)) {
                features = mlx5e_fix_uplink_rep_features(netdev, features);
+               features |= NETIF_F_NETNS_LOCAL;
+       } else {
+               features &= ~NETIF_F_NETNS_LOCAL;
+       }
 
        mutex_unlock(&priv->state_lock);
 
index 6bfed63..87a2850 100644 (file)
@@ -1103,8 +1103,8 @@ static void
 mlx5e_hairpin_params_init(struct mlx5e_hairpin_params *hairpin_params,
                          struct mlx5_core_dev *mdev)
 {
+       u32 link_speed = 0;
        u64 link_speed64;
-       u32 link_speed;
 
        hairpin_params->mdev = mdev;
        /* set hairpin pair per each 50Gbs share of the link */
index d557756..50d2ea3 100644 (file)
@@ -364,8 +364,7 @@ int mlx5_esw_acl_ingress_vport_metadata_update(struct mlx5_eswitch *esw, u16 vpo
 
        if (WARN_ON_ONCE(IS_ERR(vport))) {
                esw_warn(esw->dev, "vport(%d) invalid!\n", vport_num);
-               err = PTR_ERR(vport);
-               goto out;
+               return PTR_ERR(vport);
        }
 
        esw_acl_ingress_ofld_rules_destroy(esw, vport);
index 0f05251..8bdf287 100644 (file)
@@ -959,6 +959,7 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
         */
        esw_vport_change_handle_locked(vport);
        vport->enabled_events = 0;
+       esw_apply_vport_rx_mode(esw, vport, false, false);
        esw_vport_cleanup(esw, vport);
        esw->enabled_vports--;
 
index 2207594..25a8076 100644 (file)
@@ -3405,6 +3405,18 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
        return 0;
 }
 
+static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink)
+{
+       struct net *devl_net, *netdev_net;
+       struct mlx5_eswitch *esw;
+
+       esw = mlx5_devlink_eswitch_get(devlink);
+       netdev_net = dev_net(esw->dev->mlx5e_res.uplink_netdev);
+       devl_net = devlink_net(devlink);
+
+       return net_eq(devl_net, netdev_net);
+}
+
 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
                                  struct netlink_ext_ack *extack)
 {
@@ -3419,6 +3431,13 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
        if (esw_mode_from_devlink(mode, &mlx5_mode))
                return -EINVAL;
 
+       if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV &&
+           !esw_offloads_devlink_ns_eq_netdev_ns(devlink)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Can't change E-Switch mode to switchdev when netdev net namespace has diverged from the devlink's.");
+               return -EPERM;
+       }
+
        mlx5_lag_disable_change(esw->dev);
        err = mlx5_esw_try_lock(esw);
        if (err < 0) {
index c5240d3..09ed6e5 100644 (file)
@@ -105,7 +105,6 @@ struct mlxsw_thermal {
        struct thermal_zone_device *tzdev;
        int polling_delay;
        struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
-       u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
        struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
        struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
        struct mlxsw_thermal_area line_cards[];
@@ -468,7 +467,7 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
                return idx;
 
        /* Normalize the state to the valid speed range. */
-       state = thermal->cooling_levels[state];
+       state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state);
        mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
        err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
        if (err) {
@@ -859,10 +858,6 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
                }
        }
 
-       /* Initialize cooling levels per PWM state. */
-       for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
-               thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
-
        thermal->polling_delay = bus_info->low_frequency ?
                                 MLXSW_THERMAL_SLOW_POLL_INT :
                                 MLXSW_THERMAL_POLL_INT;
index 045a24c..b6ee2d6 100644 (file)
@@ -1354,7 +1354,7 @@ static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
                                           u16 vid)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       u8 local_port = mlxsw_sp_port->local_port;
+       u16 local_port = mlxsw_sp_port->local_port;
        int err;
 
        /* In case there are no {Port, VID} => FID mappings on the port,
@@ -1391,7 +1391,7 @@ mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
                                  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       u8 local_port = mlxsw_sp_port->local_port;
+       u16 local_port = mlxsw_sp_port->local_port;
 
        mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
        mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
index bdb8934..d0e6cd8 100644 (file)
@@ -258,6 +258,7 @@ struct ocelot_stat_layout {
 struct ocelot_stats_region {
        struct list_head node;
        u32 base;
+       enum ocelot_stat first_stat;
        int count;
        u32 *buf;
 };
@@ -273,6 +274,7 @@ static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS]
        OCELOT_STAT(RX_ASSEMBLY_OK),
        OCELOT_STAT(RX_MERGE_FRAGMENTS),
        OCELOT_STAT(TX_MERGE_FRAGMENTS),
+       OCELOT_STAT(TX_MM_HOLD),
        OCELOT_STAT(RX_PMAC_OCTETS),
        OCELOT_STAT(RX_PMAC_UNICAST),
        OCELOT_STAT(RX_PMAC_MULTICAST),
@@ -341,11 +343,12 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
  */
 static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
 {
-       unsigned int idx = port * OCELOT_NUM_STATS;
        struct ocelot_stats_region *region;
        int j;
 
        list_for_each_entry(region, &ocelot->stats_regions, node) {
+               unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat;
+
                for (j = 0; j < region->count; j++) {
                        u64 *stat = &ocelot->stats[idx + j];
                        u64 val = region->buf[j];
@@ -355,8 +358,6 @@ static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
 
                        *stat = (*stat & ~(u64)U32_MAX) + val;
                }
-
-               idx += region->count;
        }
 }
 
@@ -899,7 +900,8 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
                if (!layout[i].reg)
                        continue;
 
-               if (region && layout[i].reg == last + 4) {
+               if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] ==
+                   ocelot->map[SYS][last & REG_MASK] + 4) {
                        region->count++;
                } else {
                        region = devm_kzalloc(ocelot->dev, sizeof(*region),
@@ -914,6 +916,7 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
                        WARN_ON(last >= layout[i].reg);
 
                        region->base = layout[i].reg;
+                       region->first_stat = i;
                        region->count = 1;
                        list_add_tail(&region->node, &ocelot->stats_regions);
                }
index d17d1b4..825356e 100644 (file)
@@ -292,7 +292,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
         */
 
        laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
-       if (!laddr) {
+       if (dma_mapping_error(lp->device, laddr)) {
                pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
@@ -509,7 +509,7 @@ static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp,
 
        *new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE),
                                   SONIC_RBSIZE, DMA_FROM_DEVICE);
-       if (!*new_addr) {
+       if (dma_mapping_error(lp->device, *new_addr)) {
                dev_kfree_skb(*new_skb);
                *new_skb = NULL;
                return false;
index 2bf1874..fa167b1 100644 (file)
@@ -4404,6 +4404,9 @@ qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate)
        }
 
        vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true);
+       if (!vf)
+               return -EINVAL;
+
        vport_id = vf->vport_id;
 
        return qed_configure_vport_wfq(cdev, vport_id, rate);
@@ -5152,7 +5155,7 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
 
                /* Validate that the VF has a configured vport */
                vf = qed_iov_get_vf_info(hwfn, i, true);
-               if (!vf->vport_instance)
+               if (!vf || !vf->vport_instance)
                        continue;
 
                memset(&params, 0, sizeof(params));
index 3115b2c..eaa5005 100644 (file)
@@ -724,9 +724,15 @@ static int emac_remove(struct platform_device *pdev)
        struct net_device *netdev = dev_get_drvdata(&pdev->dev);
        struct emac_adapter *adpt = netdev_priv(netdev);
 
+       netif_carrier_off(netdev);
+       netif_tx_disable(netdev);
+
        unregister_netdev(netdev);
        netif_napi_del(&adpt->rx_q.napi);
 
+       free_irq(adpt->irq.irq, &adpt->irq);
+       cancel_work_sync(&adpt->work_thread);
+
        emac_clks_teardown(adpt);
 
        put_device(&adpt->phydev->mdio.dev);
index 6b5d96b..ec9c130 100644 (file)
@@ -418,6 +418,7 @@ struct dma_features {
        unsigned int frpbs;
        unsigned int frpes;
        unsigned int addr64;
+       unsigned int host_dma_width;
        unsigned int rssen;
        unsigned int vlhash;
        unsigned int sphen;
index ac550d1..2a2be65 100644 (file)
@@ -288,7 +288,7 @@ static int imx_dwmac_probe(struct platform_device *pdev)
                goto err_parse_dt;
        }
 
-       plat_dat->addr64 = dwmac->ops->addr_width;
+       plat_dat->host_dma_width = dwmac->ops->addr_width;
        plat_dat->init = imx_dwmac_init;
        plat_dat->exit = imx_dwmac_exit;
        plat_dat->clks_config = imx_dwmac_clks_config;
index 7deb1f8..13aa919 100644 (file)
@@ -684,7 +684,7 @@ static int ehl_pse0_common_data(struct pci_dev *pdev,
 
        intel_priv->is_pse = true;
        plat->bus_id = 2;
-       plat->addr64 = 32;
+       plat->host_dma_width = 32;
 
        plat->clk_ptp_rate = 200000000;
 
@@ -725,7 +725,7 @@ static int ehl_pse1_common_data(struct pci_dev *pdev,
 
        intel_priv->is_pse = true;
        plat->bus_id = 3;
-       plat->addr64 = 32;
+       plat->host_dma_width = 32;
 
        plat->clk_ptp_rate = 200000000;
 
index 2f7d8e4..9ae31e3 100644 (file)
@@ -591,7 +591,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
        plat->use_phy_wol = priv_plat->mac_wol ? 0 : 1;
        plat->riwt_off = 1;
        plat->maxmtu = ETH_DATA_LEN;
-       plat->addr64 = priv_plat->variant->dma_bit_mask;
+       plat->host_dma_width = priv_plat->variant->dma_bit_mask;
        plat->bsp_priv = priv_plat;
        plat->init = mediatek_dwmac_init;
        plat->clks_config = mediatek_dwmac_clks_config;
index 8f543c3..17310ad 100644 (file)
@@ -1431,7 +1431,7 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv,
        struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
        gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
 
-       if (priv->dma_cap.addr64 <= 32)
+       if (priv->dma_cap.host_dma_width <= 32)
                gfp |= GFP_DMA32;
 
        if (!buf->page) {
@@ -4587,7 +4587,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
        unsigned int entry = rx_q->dirty_rx;
        gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
 
-       if (priv->dma_cap.addr64 <= 32)
+       if (priv->dma_cap.host_dma_width <= 32)
                gfp |= GFP_DMA32;
 
        while (dirty-- > 0) {
@@ -6205,7 +6205,7 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
        seq_printf(seq, "\tFlexible RX Parser: %s\n",
                   priv->dma_cap.frpsel ? "Y" : "N");
        seq_printf(seq, "\tEnhanced Addressing: %d\n",
-                  priv->dma_cap.addr64);
+                  priv->dma_cap.host_dma_width);
        seq_printf(seq, "\tReceive Side Scaling: %s\n",
                   priv->dma_cap.rssen ? "Y" : "N");
        seq_printf(seq, "\tVLAN Hash Filtering: %s\n",
@@ -7178,20 +7178,22 @@ int stmmac_dvr_probe(struct device *device,
                dev_info(priv->device, "SPH feature enabled\n");
        }
 
-       /* The current IP register MAC_HW_Feature1[ADDR64] only define
-        * 32/40/64 bit width, but some SOC support others like i.MX8MP
-        * support 34 bits but it map to 40 bits width in MAC_HW_Feature1[ADDR64].
-        * So overwrite dma_cap.addr64 according to HW real design.
+       /* Ideally our host DMA address width is the same as for the
+        * device. However, it may differ and then we have to use our
+        * host DMA width for allocation and the device DMA width for
+        * register handling.
         */
-       if (priv->plat->addr64)
-               priv->dma_cap.addr64 = priv->plat->addr64;
+       if (priv->plat->host_dma_width)
+               priv->dma_cap.host_dma_width = priv->plat->host_dma_width;
+       else
+               priv->dma_cap.host_dma_width = priv->dma_cap.addr64;
 
-       if (priv->dma_cap.addr64) {
+       if (priv->dma_cap.host_dma_width) {
                ret = dma_set_mask_and_coherent(device,
-                               DMA_BIT_MASK(priv->dma_cap.addr64));
+                               DMA_BIT_MASK(priv->dma_cap.host_dma_width));
                if (!ret) {
-                       dev_info(priv->device, "Using %d bits DMA width\n",
-                                priv->dma_cap.addr64);
+                       dev_info(priv->device, "Using %d/%d bits DMA host/device width\n",
+                                priv->dma_cap.host_dma_width, priv->dma_cap.addr64);
 
                        /*
                         * If more than 32 bits can be addressed, make sure to
@@ -7206,7 +7208,7 @@ int stmmac_dvr_probe(struct device *device,
                                goto error_hw_init;
                        }
 
-                       priv->dma_cap.addr64 = 32;
+                       priv->dma_cap.host_dma_width = 32;
                }
        }
 
index 16ee9c2..8caf85a 100644 (file)
@@ -636,6 +636,10 @@ static void am65_cpts_perout_enable_hw(struct am65_cpts *cpts,
                val = lower_32_bits(cycles);
                am65_cpts_write32(cpts, val, genf[req->index].length);
 
+               am65_cpts_write32(cpts, 0, genf[req->index].control);
+               am65_cpts_write32(cpts, 0, genf[req->index].ppm_hi);
+               am65_cpts_write32(cpts, 0, genf[req->index].ppm_low);
+
                cpts->genf_enable |= BIT(req->index);
        } else {
                am65_cpts_write32(cpts, 0, genf[req->index].length);
index cf8de8a..9d535ae 100644 (file)
@@ -317,15 +317,17 @@ static int gelic_card_init_chain(struct gelic_card *card,
 
        /* set up the hardware pointers in each descriptor */
        for (i = 0; i < no; i++, descr++) {
+               dma_addr_t cpu_addr;
+
                gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE);
-               descr->bus_addr =
-                       dma_map_single(ctodev(card), descr,
-                                      GELIC_DESCR_SIZE,
-                                      DMA_BIDIRECTIONAL);
 
-               if (!descr->bus_addr)
+               cpu_addr = dma_map_single(ctodev(card), descr,
+                                         GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL);
+
+               if (dma_mapping_error(ctodev(card), cpu_addr))
                        goto iommu_error;
 
+               descr->bus_addr = cpu_to_be32(cpu_addr);
                descr->next = descr + 1;
                descr->prev = descr - 1;
        }
@@ -365,26 +367,28 @@ iommu_error:
  *
  * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
  * Activate the descriptor state-wise
+ *
+ * Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length
+ * must be a multiple of GELIC_NET_RXBUF_ALIGN.
  */
 static int gelic_descr_prepare_rx(struct gelic_card *card,
                                  struct gelic_descr *descr)
 {
+       static const unsigned int rx_skb_size =
+               ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) +
+               GELIC_NET_RXBUF_ALIGN - 1;
+       dma_addr_t cpu_addr;
        int offset;
-       unsigned int bufsize;
 
        if (gelic_descr_get_status(descr) !=  GELIC_DESCR_DMA_NOT_IN_USE)
                dev_info(ctodev(card), "%s: ERROR status\n", __func__);
-       /* we need to round up the buffer size to a multiple of 128 */
-       bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
 
-       /* and we need to have it 128 byte aligned, therefore we allocate a
-        * bit more */
-       descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+       descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size);
        if (!descr->skb) {
                descr->buf_addr = 0; /* tell DMAC don't touch memory */
                return -ENOMEM;
        }
-       descr->buf_size = cpu_to_be32(bufsize);
+       descr->buf_size = cpu_to_be32(rx_skb_size);
        descr->dmac_cmd_status = 0;
        descr->result_size = 0;
        descr->valid_size = 0;
@@ -395,11 +399,10 @@ static int gelic_descr_prepare_rx(struct gelic_card *card,
        if (offset)
                skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
        /* io-mmu-map the skb */
-       descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card),
-                                                    descr->skb->data,
-                                                    GELIC_NET_MAX_MTU,
-                                                    DMA_FROM_DEVICE));
-       if (!descr->buf_addr) {
+       cpu_addr = dma_map_single(ctodev(card), descr->skb->data,
+                                 GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE);
+       descr->buf_addr = cpu_to_be32(cpu_addr);
+       if (dma_mapping_error(ctodev(card), cpu_addr)) {
                dev_kfree_skb_any(descr->skb);
                descr->skb = NULL;
                dev_info(ctodev(card),
@@ -779,7 +782,7 @@ static int gelic_descr_prepare_tx(struct gelic_card *card,
 
        buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE);
 
-       if (!buf) {
+       if (dma_mapping_error(ctodev(card), buf)) {
                dev_err(ctodev(card),
                        "dma map 2 failed (%p, %i). Dropping packet\n",
                        skb->data, skb->len);
@@ -915,7 +918,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr,
        data_error = be32_to_cpu(descr->data_error);
        /* unmap skb buffer */
        dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr),
-                        GELIC_NET_MAX_MTU,
+                        GELIC_NET_MAX_FRAME,
                         DMA_FROM_DEVICE);
 
        skb_put(skb, be32_to_cpu(descr->valid_size)?
index 68f324e..0d98def 100644 (file)
@@ -19,8 +19,9 @@
 #define GELIC_NET_RX_DESCRIPTORS        128 /* num of descriptors */
 #define GELIC_NET_TX_DESCRIPTORS        128 /* num of descriptors */
 
-#define GELIC_NET_MAX_MTU               VLAN_ETH_FRAME_LEN
-#define GELIC_NET_MIN_MTU               VLAN_ETH_ZLEN
+#define GELIC_NET_MAX_FRAME             2312
+#define GELIC_NET_MAX_MTU               2294
+#define GELIC_NET_MIN_MTU               64
 #define GELIC_NET_RXBUF_ALIGN           128
 #define GELIC_CARD_RX_CSUM_DEFAULT      1 /* hw chksum */
 #define GELIC_NET_WATCHDOG_TIMEOUT      5*HZ
index 894e92e..9f505cf 100644 (file)
@@ -503,6 +503,11 @@ static void
 xirc2ps_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
+    struct local_info *local = netdev_priv(dev);
+
+    netif_carrier_off(dev);
+    netif_tx_disable(dev);
+    cancel_work_sync(&local->tx_timeout_task);
 
     dev_dbg(&link->dev, "detach\n");
 
index d77c987..4630dde 100644 (file)
@@ -18,16 +18,18 @@ MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
 MODULE_LICENSE("GPL");
 
 /**
- * acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
+ * __acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
  * @mdio: pointer to mii_bus structure
  * @fwnode: pointer to fwnode of MDIO bus. This fwnode is expected to represent
+ * @owner: module owning this @mdio object.
  * an ACPI device object corresponding to the MDIO bus and its children are
  * expected to correspond to the PHY devices on that bus.
  *
  * This function registers the mii_bus structure and registers a phy_device
  * for each child node of @fwnode.
  */
-int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
+int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode,
+                           struct module *owner)
 {
        struct fwnode_handle *child;
        u32 addr;
@@ -35,7 +37,7 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
 
        /* Mask out all PHYs from auto probing. */
        mdio->phy_mask = GENMASK(31, 0);
-       ret = mdiobus_register(mdio);
+       ret = __mdiobus_register(mdio, owner);
        if (ret)
                return ret;
 
@@ -55,4 +57,4 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
        }
        return 0;
 }
-EXPORT_SYMBOL(acpi_mdiobus_register);
+EXPORT_SYMBOL(__acpi_mdiobus_register);
index 3847ee9..6067d96 100644 (file)
@@ -106,6 +106,7 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
                if (i >= ARRAY_SIZE(nexus->buses))
                        break;
        }
+       fwnode_handle_put(fwn);
        return 0;
 
 err_release_regions:
index 510822d..1e46e39 100644 (file)
@@ -139,21 +139,23 @@ bool of_mdiobus_child_is_phy(struct device_node *child)
 EXPORT_SYMBOL(of_mdiobus_child_is_phy);
 
 /**
- * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
+ * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree
  * @mdio: pointer to mii_bus structure
  * @np: pointer to device_node of MDIO bus.
+ * @owner: module owning the @mdio object.
  *
  * This function registers the mii_bus structure and registers a phy_device
  * for each child node of @np.
  */
-int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
+int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
+                         struct module *owner)
 {
        struct device_node *child;
        bool scanphys = false;
        int addr, rc;
 
        if (!np)
-               return mdiobus_register(mdio);
+               return __mdiobus_register(mdio, owner);
 
        /* Do not continue if the node is disabled */
        if (!of_device_is_available(np))
@@ -172,7 +174,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        of_property_read_u32(np, "reset-post-delay-us", &mdio->reset_post_delay_us);
 
        /* Register the MDIO bus */
-       rc = mdiobus_register(mdio);
+       rc = __mdiobus_register(mdio, owner);
        if (rc)
                return rc;
 
@@ -236,7 +238,7 @@ unregister:
        mdiobus_unregister(mdio);
        return rc;
 }
-EXPORT_SYMBOL(of_mdiobus_register);
+EXPORT_SYMBOL(__of_mdiobus_register);
 
 /**
  * of_mdio_find_device - Given a device tree node, find the mdio_device
index b560e99..69b829e 100644 (file)
@@ -98,13 +98,14 @@ EXPORT_SYMBOL(__devm_mdiobus_register);
 
 #if IS_ENABLED(CONFIG_OF_MDIO)
 /**
- * devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
+ * __devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
  * @dev:       Device to register mii_bus for
  * @mdio:      MII bus structure to register
  * @np:                Device node to parse
+ * @owner:     Owning module
  */
-int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
-                            struct device_node *np)
+int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
+                              struct device_node *np, struct module *owner)
 {
        struct mdiobus_devres *dr;
        int ret;
@@ -117,7 +118,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
        if (!dr)
                return -ENOMEM;
 
-       ret = of_mdiobus_register(mdio, np);
+       ret = __of_mdiobus_register(mdio, np, owner);
        if (ret) {
                devres_free(dr);
                return ret;
@@ -127,7 +128,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
        devres_add(dev, dr);
        return 0;
 }
-EXPORT_SYMBOL(devm_of_mdiobus_register);
+EXPORT_SYMBOL(__devm_of_mdiobus_register);
 #endif /* CONFIG_OF_MDIO */
 
 MODULE_LICENSE("GPL");
index b33e55a..99a07eb 100644 (file)
@@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st)
        return NULL;
 }
 
+static void phy_process_state_change(struct phy_device *phydev,
+                                    enum phy_state old_state)
+{
+       if (old_state != phydev->state) {
+               phydev_dbg(phydev, "PHY state change %s -> %s\n",
+                          phy_state_to_str(old_state),
+                          phy_state_to_str(phydev->state));
+               if (phydev->drv && phydev->drv->link_change_notify)
+                       phydev->drv->link_change_notify(phydev);
+       }
+}
+
 static void phy_link_up(struct phy_device *phydev)
 {
        phydev->phy_link_change(phydev, true);
@@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
 void phy_stop(struct phy_device *phydev)
 {
        struct net_device *dev = phydev->attached_dev;
+       enum phy_state old_state;
 
        if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
                WARN(1, "called from state %s\n",
@@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev)
        }
 
        mutex_lock(&phydev->lock);
+       old_state = phydev->state;
 
        if (phydev->state == PHY_CABLETEST) {
                phy_abort_cable_test(phydev);
@@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev)
                sfp_upstream_stop(phydev->sfp_bus);
 
        phydev->state = PHY_HALTED;
+       phy_process_state_change(phydev, old_state);
 
        mutex_unlock(&phydev->lock);
 
@@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work)
        if (err < 0)
                phy_error(phydev);
 
-       if (old_state != phydev->state) {
-               phydev_dbg(phydev, "PHY state change %s -> %s\n",
-                          phy_state_to_str(old_state),
-                          phy_state_to_str(phydev->state));
-               if (phydev->drv && phydev->drv->link_change_notify)
-                       phydev->drv->link_change_notify(phydev);
-       }
+       phy_process_state_change(phydev, old_state);
 
        /* Only re-schedule a PHY state machine change if we are polling the
         * PHY, if PHY_MAC_INTERRUPT is set, then we will be moving
index c02cad6..fb98db6 100644 (file)
@@ -2190,6 +2190,11 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
                        break;
                }
 
+               /* Force a poll to re-read the hardware signal state after
+                * sfp_sm_mod_probe() changed state_hw_mask.
+                */
+               mod_delayed_work(system_wq, &sfp->poll, 1);
+
                err = sfp_hwmon_insert(sfp);
                if (err)
                        dev_warn(sfp->dev, "hwmon probe failed: %pe\n",
index 743cbf5..f7cff58 100644 (file)
@@ -666,8 +666,9 @@ static int asix_resume(struct usb_interface *intf)
 static int ax88772_init_mdio(struct usbnet *dev)
 {
        struct asix_common_private *priv = dev->driver_priv;
+       int ret;
 
-       priv->mdio = devm_mdiobus_alloc(&dev->udev->dev);
+       priv->mdio = mdiobus_alloc();
        if (!priv->mdio)
                return -ENOMEM;
 
@@ -679,7 +680,20 @@ static int ax88772_init_mdio(struct usbnet *dev)
        snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
                 dev->udev->bus->busnum, dev->udev->devnum);
 
-       return devm_mdiobus_register(&dev->udev->dev, priv->mdio);
+       ret = mdiobus_register(priv->mdio);
+       if (ret) {
+               netdev_err(dev->net, "Could not register MDIO bus (err %d)\n", ret);
+               mdiobus_free(priv->mdio);
+               priv->mdio = NULL;
+       }
+
+       return ret;
+}
+
+static void ax88772_mdio_unregister(struct asix_common_private *priv)
+{
+       mdiobus_unregister(priv->mdio);
+       mdiobus_free(priv->mdio);
 }
 
 static int ax88772_init_phy(struct usbnet *dev)
@@ -896,16 +910,23 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 
        ret = ax88772_init_mdio(dev);
        if (ret)
-               return ret;
+               goto mdio_err;
 
        ret = ax88772_phylink_setup(dev);
        if (ret)
-               return ret;
+               goto phylink_err;
 
        ret = ax88772_init_phy(dev);
        if (ret)
-               phylink_destroy(priv->phylink);
+               goto initphy_err;
 
+       return 0;
+
+initphy_err:
+       phylink_destroy(priv->phylink);
+phylink_err:
+       ax88772_mdio_unregister(priv);
+mdio_err:
        return ret;
 }
 
@@ -926,6 +947,7 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
        phylink_disconnect_phy(priv->phylink);
        rtnl_unlock();
        phylink_destroy(priv->phylink);
+       ax88772_mdio_unregister(priv);
        asix_rx_fixup_common_free(dev->driver_priv);
 }
 
index 0684888..c458c03 100644 (file)
@@ -3579,13 +3579,29 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb,
                size = (rx_cmd_a & RX_CMD_A_LEN_MASK_);
                align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
 
+               if (unlikely(size > skb->len)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "size err rx_cmd_a=0x%08x\n",
+                                 rx_cmd_a);
+                       return 0;
+               }
+
                if (unlikely(rx_cmd_a & RX_CMD_A_RED_)) {
                        netif_dbg(dev, rx_err, dev->net,
                                  "Error rx_cmd_a=0x%08x", rx_cmd_a);
                } else {
-                       u32 frame_len = size - ETH_FCS_LEN;
+                       u32 frame_len;
                        struct sk_buff *skb2;
 
+                       if (unlikely(size < ETH_FCS_LEN)) {
+                               netif_dbg(dev, rx_err, dev->net,
+                                         "size err rx_cmd_a=0x%08x\n",
+                                         rx_cmd_a);
+                               return 0;
+                       }
+
+                       frame_len = size - ETH_FCS_LEN;
+
                        skb2 = napi_alloc_skb(&dev->napi, frame_len);
                        if (!skb2)
                                return 0;
index 7a2b009..2894114 100644 (file)
@@ -62,12 +62,6 @@ pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
 }
 
 static inline int
-pl_clear_QuickLink_features(struct usbnet *dev, int val)
-{
-       return pl_vendor_req(dev, 1, (u8) val, 0);
-}
-
-static inline int
 pl_set_QuickLink_features(struct usbnet *dev, int val)
 {
        return pl_vendor_req(dev, 3, (u8) val, 0);
index 32d2c60..563ecd2 100644 (file)
@@ -1833,6 +1833,12 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                size = (u16)((header & RX_STS_FL_) >> 16);
                align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
 
+               if (unlikely(size > skb->len)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "size err header=0x%08x\n", header);
+                       return 0;
+               }
+
                if (unlikely(header & RX_STS_ES_)) {
                        netif_dbg(dev, rx_err, dev->net,
                                  "Error header=0x%08x\n", header);
index a30a66c..c117891 100644 (file)
@@ -1642,7 +1642,7 @@ static int veth_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        struct veth_xdp_buff *_ctx = (void *)ctx;
 
        if (!_ctx->skb)
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *timestamp = skb_hwtstamps(_ctx->skb)->hwtstamp;
        return 0;
@@ -1653,7 +1653,7 @@ static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
        struct veth_xdp_buff *_ctx = (void *)ctx;
 
        if (!_ctx->skb)
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *hash = skb_get_hash(_ctx->skb);
        return 0;
index 5655224..b55b1b1 100644 (file)
@@ -732,7 +732,10 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
 
        rcu_read_lock();
        do {
-               while (likely(!mvmtxq->stopped &&
+               while (likely(!test_bit(IWL_MVM_TXQ_STATE_STOP_FULL,
+                                       &mvmtxq->state) &&
+                             !test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT,
+                                       &mvmtxq->state) &&
                              !test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) {
                        skb = ieee80211_tx_dequeue(hw, txq);
 
@@ -757,42 +760,25 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
 
-       /*
-        * Please note that racing is handled very carefully here:
-        * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
-        * deleted afterwards.
-        * This means that if:
-        * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
-        *      queue is allocated and we can TX.
-        * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
-        *      a race, should defer the frame.
-        * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
-        *      need to allocate the queue and defer the frame.
-        * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
-        *      queue is already scheduled for allocation, no need to allocate,
-        *      should defer the frame.
-        */
-
-       /* If the queue is allocated TX and return. */
-       if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
-               /*
-                * Check that list is empty to avoid a race where txq_id is
-                * already updated, but the queue allocation work wasn't
-                * finished
-                */
-               if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
-                       return;
-
+       if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
+           !txq->sta) {
                iwl_mvm_mac_itxq_xmit(hw, txq);
                return;
        }
 
-       /* The list is being deleted only after the queue is fully allocated. */
-       if (!list_empty(&mvmtxq->list))
-               return;
+       /* iwl_mvm_mac_itxq_xmit() will later be called by the worker
+        * to handle any packets we leave on the txq now
+        */
 
-       list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
-       schedule_work(&mvm->add_stream_wk);
+       spin_lock_bh(&mvm->add_stream_lock);
+       /* The list is being deleted only after the queue is fully allocated. */
+       if (list_empty(&mvmtxq->list) &&
+           /* recheck under lock */
+           !test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) {
+               list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
+               schedule_work(&mvm->add_stream_wk);
+       }
+       spin_unlock_bh(&mvm->add_stream_lock);
 }
 
 #define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...)          \
index 90bc95d..f307c34 100644 (file)
@@ -729,7 +729,10 @@ struct iwl_mvm_txq {
        struct list_head list;
        u16 txq_id;
        atomic_t tx_request;
-       bool stopped;
+#define IWL_MVM_TXQ_STATE_STOP_FULL    0
+#define IWL_MVM_TXQ_STATE_STOP_REDIRECT        1
+#define IWL_MVM_TXQ_STATE_READY                2
+       unsigned long state;
 };
 
 static inline struct iwl_mvm_txq *
@@ -827,6 +830,7 @@ struct iwl_mvm {
                struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES];
        };
        struct work_struct add_stream_wk; /* To add streams to queues */
+       spinlock_t add_stream_lock;
 
        const char *nvm_file_name;
        struct iwl_nvm_data *nvm_data;
index f4e9446..9711841 100644 (file)
@@ -1195,6 +1195,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
        INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
        INIT_LIST_HEAD(&mvm->add_stream_txqs);
+       spin_lock_init(&mvm->add_stream_lock);
 
        init_waitqueue_head(&mvm->rx_sync_waitq);
 
@@ -1691,7 +1692,10 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
 
                txq = sta->txq[tid];
                mvmtxq = iwl_mvm_txq_from_mac80211(txq);
-               mvmtxq->stopped = !start;
+               if (start)
+                       clear_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
+               else
+                       set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
 
                if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
                        iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
index 69634fb..9caae77 100644 (file)
@@ -384,8 +384,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                struct iwl_mvm_txq *mvmtxq =
                        iwl_mvm_txq_from_tid(sta, tid);
 
-               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_lock_bh(&mvm->add_stream_lock);
                list_del_init(&mvmtxq->list);
+               clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_unlock_bh(&mvm->add_stream_lock);
        }
 
        /* Regardless if this is a reserved TXQ for a STA - mark it as false */
@@ -479,8 +482,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
                        disable_agg_tids |= BIT(tid);
                mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
 
-               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_lock_bh(&mvm->add_stream_lock);
                list_del_init(&mvmtxq->list);
+               clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_unlock_bh(&mvm->add_stream_lock);
        }
 
        mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */
@@ -693,7 +699,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
                            queue, iwl_mvm_ac_to_tx_fifo[ac]);
 
        /* Stop the queue and wait for it to empty */
-       txq->stopped = true;
+       set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
 
        ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));
        if (ret) {
@@ -736,7 +742,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
 
 out:
        /* Continue using the queue */
-       txq->stopped = false;
+       clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
 
        return ret;
 }
@@ -1444,12 +1450,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
                 * a queue in the function itself.
                 */
                if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) {
+                       spin_lock_bh(&mvm->add_stream_lock);
                        list_del_init(&mvmtxq->list);
+                       spin_unlock_bh(&mvm->add_stream_lock);
                        continue;
                }
 
-               list_del_init(&mvmtxq->list);
+               /* now we're ready, any remaining races/concurrency will be
+                * handled in iwl_mvm_mac_itxq_xmit()
+                */
+               set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+
                local_bh_disable();
+               spin_lock(&mvm->add_stream_lock);
+               list_del_init(&mvmtxq->list);
+               spin_unlock(&mvm->add_stream_lock);
+
                iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
                local_bh_enable();
        }
@@ -1864,8 +1880,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
                struct iwl_mvm_txq *mvmtxq =
                        iwl_mvm_txq_from_mac80211(sta->txq[i]);
 
+               spin_lock_bh(&mvm->add_stream_lock);
                mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
                list_del_init(&mvmtxq->list);
+               clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               spin_unlock_bh(&mvm->add_stream_lock);
        }
 }
 
index 5dcf617..9a698a1 100644 (file)
@@ -172,7 +172,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
        .can_ext_scan = true,
 };
 
-static const struct of_device_id mwifiex_pcie_of_match_table[] = {
+static const struct of_device_id mwifiex_pcie_of_match_table[] __maybe_unused = {
        { .compatible = "pci11ab,2b42" },
        { .compatible = "pci1b4b,2b42" },
        { }
index c64e24c..a24bd40 100644 (file)
@@ -495,7 +495,7 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
        {"EXTLAST", NULL, 0, 0xFE},
 };
 
-static const struct of_device_id mwifiex_sdio_of_match_table[] = {
+static const struct of_device_id mwifiex_sdio_of_match_table[] __maybe_unused = {
        { .compatible = "marvell,sd8787" },
        { .compatible = "marvell,sd8897" },
        { .compatible = "marvell,sd8978" },
index b117e44..34abf70 100644 (file)
@@ -539,6 +539,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
        if (ret)
                return ret;
 
+       set_bit(MT76_STATE_REGISTERED, &phy->state);
        phy->dev->phys[phy->band_idx] = phy;
 
        return 0;
@@ -549,6 +550,9 @@ void mt76_unregister_phy(struct mt76_phy *phy)
 {
        struct mt76_dev *dev = phy->dev;
 
+       if (!test_bit(MT76_STATE_REGISTERED, &phy->state))
+               return;
+
        if (IS_ENABLED(CONFIG_MT76_LEDS))
                mt76_led_cleanup(phy);
        mt76_tx_status_check(dev, true);
@@ -719,6 +723,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
                return ret;
 
        WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
+       set_bit(MT76_STATE_REGISTERED, &phy->state);
        sched_set_fifo_low(dev->tx_worker.task);
 
        return 0;
@@ -729,6 +734,9 @@ void mt76_unregister_device(struct mt76_dev *dev)
 {
        struct ieee80211_hw *hw = dev->hw;
 
+       if (!test_bit(MT76_STATE_REGISTERED, &dev->phy.state))
+               return;
+
        if (IS_ENABLED(CONFIG_MT76_LEDS))
                mt76_led_cleanup(&dev->phy);
        mt76_tx_status_check(dev, true);
index ccca016..183b0fc 100644 (file)
@@ -402,6 +402,7 @@ struct mt76_tx_cb {
 
 enum {
        MT76_STATE_INITIALIZED,
+       MT76_STATE_REGISTERED,
        MT76_STATE_RUNNING,
        MT76_STATE_MCU_RUNNING,
        MT76_SCANNING,
index efb9bfa..008ece1 100644 (file)
@@ -1221,6 +1221,9 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv);
 
 int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb)
 {
+       if (!mt76_is_mmio(dev))
+               return 0;
+
        if (!mtk_wed_device_active(&dev->mmio.wed))
                return 0;
 
index 1ab768f..5e28811 100644 (file)
@@ -383,7 +383,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
        ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
        ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
        ieee80211_hw_set(hw, WANT_MONITOR_VIF);
-       ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
 
        hw->max_tx_fragments = 4;
 
@@ -396,6 +395,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
        }
 
        if (phy->mt76->cap.has_5ghz) {
+               struct ieee80211_sta_vht_cap *vht_cap;
+
+               vht_cap = &phy->mt76->sband_5g.sband.vht_cap;
                phy->mt76->sband_5g.sband.ht_cap.cap |=
                        IEEE80211_HT_CAP_LDPC_CODING |
                        IEEE80211_HT_CAP_MAX_AMSDU;
@@ -403,19 +405,28 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
                        IEEE80211_HT_MPDU_DENSITY_4;
 
                if (is_mt7915(&dev->mt76)) {
-                       phy->mt76->sband_5g.sband.vht_cap.cap |=
+                       vht_cap->cap |=
                                IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
                                IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+
+                       if (!dev->dbdc_support)
+                               vht_cap->cap |=
+                                       IEEE80211_VHT_CAP_SHORT_GI_160 |
+                                       IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+                                       FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
                } else {
-                       phy->mt76->sband_5g.sband.vht_cap.cap |=
+                       vht_cap->cap |=
                                IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
                                IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
 
                        /* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */
-                       phy->mt76->sband_5g.sband.vht_cap.cap |=
+                       vht_cap->cap |=
                                IEEE80211_VHT_CAP_SHORT_GI_160 |
                                IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
                }
+
+               if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)
+                       ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
        }
 
        mt76_set_stream_caps(phy->mt76, true);
@@ -841,9 +852,13 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
        int sts = hweight8(phy->mt76->chainmask);
        u8 c, sts_160 = sts;
 
-       /* mt7915 doesn't support bw160 */
-       if (is_mt7915(&dev->mt76))
-               sts_160 = 0;
+       /* Can do 1/2 of STS in 160Mhz mode for mt7915 */
+       if (is_mt7915(&dev->mt76)) {
+               if (!dev->dbdc_support)
+                       sts_160 /= 2;
+               else
+                       sts_160 = 0;
+       }
 
 #ifdef CONFIG_MAC80211_MESH
        if (vif == NL80211_IFTYPE_MESH_POINT)
@@ -944,10 +959,15 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
        int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
        u16 mcs_map = 0;
        u16 mcs_map_160 = 0;
-       u8 nss_160 = nss;
+       u8 nss_160;
 
-       /* Can't do 160MHz with mt7915 */
-       if (is_mt7915(&dev->mt76))
+       if (!is_mt7915(&dev->mt76))
+               nss_160 = nss;
+       else if (!dev->dbdc_support)
+               /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
+               nss_160 = nss / 2;
+       else
+               /* Can't do 160MHz with mt7915 dbdc */
                nss_160 = 0;
 
        for (i = 0; i < 8; i++) {
index d4be525..53ef028 100644 (file)
@@ -3063,7 +3063,8 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
        else
                ctrl->max_zeroes_sectors = 0;
 
-       if (nvme_ctrl_limited_cns(ctrl))
+       if (ctrl->subsys->subtype != NVME_NQN_NVME ||
+           nvme_ctrl_limited_cns(ctrl))
                return 0;
 
        id = kzalloc(sizeof(*id), GFP_KERNEL);
index 723e7d5..d24ea2e 100644 (file)
@@ -464,7 +464,8 @@ static inline struct nvme_uring_cmd_pdu *nvme_uring_cmd_pdu(
        return (struct nvme_uring_cmd_pdu *)&ioucmd->pdu;
 }
 
-static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd)
+static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd,
+                                   unsigned issue_flags)
 {
        struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
        struct request *req = pdu->req;
@@ -485,17 +486,18 @@ static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd)
                blk_rq_unmap_user(req->bio);
        blk_mq_free_request(req);
 
-       io_uring_cmd_done(ioucmd, status, result);
+       io_uring_cmd_done(ioucmd, status, result, issue_flags);
 }
 
-static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd)
+static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd,
+                              unsigned issue_flags)
 {
        struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
 
        if (pdu->bio)
                blk_rq_unmap_user(pdu->bio);
 
-       io_uring_cmd_done(ioucmd, pdu->nvme_status, pdu->u.result);
+       io_uring_cmd_done(ioucmd, pdu->nvme_status, pdu->u.result, issue_flags);
 }
 
 static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
@@ -517,7 +519,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
         * Otherwise, move the completion to task work.
         */
        if (cookie != NULL && blk_rq_is_poll(req))
-               nvme_uring_task_cb(ioucmd);
+               nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED);
        else
                io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb);
 
@@ -539,7 +541,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
         * Otherwise, move the completion to task work.
         */
        if (cookie != NULL && blk_rq_is_poll(req))
-               nvme_uring_task_meta_cb(ioucmd);
+               nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED);
        else
                io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_meta_cb);
 
index 0de7c25..d6de5a2 100644 (file)
@@ -284,7 +284,7 @@ static long cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
            u_cmd.insize > EC_MAX_MSG_BYTES)
                return -EINVAL;
 
-       s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
+       s_cmd = kzalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
                        GFP_KERNEL);
        if (!s_cmd)
                return -ENOMEM;
index 8e6f8a6..05f4131 100644 (file)
@@ -724,6 +724,8 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 
        for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
                pirq = platform_get_irq(pdev, i);
+               if (pirq < 0)
+                       continue;
                ret = regmap_irq_get_virq(axp20x->regmap_irqc, pirq);
                if (ret < 0)
                        return dev_err_probe(dev, ret, "getting vIRQ %d\n", pirq);
index be34b98..de67b98 100644 (file)
@@ -1906,6 +1906,7 @@ static void bq24190_remove(struct i2c_client *client)
        struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
        int error;
 
+       cancel_delayed_work_sync(&bdi->input_current_limit_work);
        error = pm_runtime_resume_and_get(bdi->dev);
        if (error < 0)
                dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
index cadb6a0..b6c9637 100644 (file)
@@ -276,7 +276,7 @@ static int cros_usbpd_charger_get_power_info(struct port_data *port)
                port->psy_current_max = 0;
                break;
        default:
-               dev_err(dev, "Port %d: default case!\n", port->port_number);
+               dev_dbg(dev, "Port %d: default case!\n", port->port_number);
                port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
        }
 
index 14da5c5..a87aeae 100644 (file)
@@ -657,6 +657,7 @@ static int da9150_charger_remove(struct platform_device *pdev)
 
        if (!IS_ERR_OR_NULL(charger->usb_phy))
                usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+       cancel_work_sync(&charger->otg_work);
 
        power_supply_unregister(charger->battery);
        power_supply_unregister(charger->usb);
index 4f9c1c4..36f807b 100644 (file)
@@ -785,8 +785,6 @@ rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger,
                regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
                                 bulk_reg, 4);
                tmp = get_unaligned_be32(bulk_reg);
-               if (tmp < 0)
-                       tmp = 0;
                boot_charge_mah = ADC_TO_CHARGE_UAH(tmp,
                                                    charger->res_div) / 1000;
                /*
@@ -825,8 +823,6 @@ rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger,
        regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
                         bulk_reg, 4);
        tmp = get_unaligned_be32(bulk_reg);
-       if (tmp < 0)
-               tmp = 0;
        boot_charge_mah = ADC_TO_CHARGE_UAH(tmp, charger->res_div) / 1000;
        regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_OCV_VOL_H,
                         bulk_reg, 2);
index 362fa63..a226dc1 100644 (file)
@@ -1145,10 +1145,12 @@ static int alua_activate(struct scsi_device *sdev,
        rcu_read_unlock();
        mutex_unlock(&h->init_mutex);
 
-       if (alua_rtpg_queue(pg, sdev, qdata, true))
+       if (alua_rtpg_queue(pg, sdev, qdata, true)) {
                fn = NULL;
-       else
+       } else {
+               kfree(qdata);
                err = SCSI_DH_DEV_OFFLINED;
+       }
        kref_put(&pg->kref, release_port_group);
 out:
        if (fn)
index 030625e..71feda2 100644 (file)
@@ -1900,6 +1900,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
        }
 
        req->outstanding_cmds[index] = NULL;
+
+       qla_put_fw_resources(sp->qpair, &sp->iores);
        return sp;
 }
 
@@ -3112,7 +3114,6 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
        }
        bsg_reply->reply_payload_rcv_len = 0;
 
-       qla_put_fw_resources(sp->qpair, &sp->iores);
 done:
        /* Return the vendor specific reply to API */
        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
index 80c4ee9..bee1b8a 100644 (file)
@@ -1865,6 +1865,17 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
        for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
                sp = req->outstanding_cmds[cnt];
                if (sp) {
+                       /*
+                        * perform lockless completion during driver unload
+                        */
+                       if (qla2x00_chip_is_down(vha)) {
+                               req->outstanding_cmds[cnt] = NULL;
+                               spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
+                               sp->done(sp, res);
+                               spin_lock_irqsave(qp->qp_lock_ptr, flags);
+                               continue;
+                       }
+
                        switch (sp->cmd_type) {
                        case TYPE_SRB:
                                qla2x00_abort_srb(qp, sp, res, &flags);
index bc9d280..3fcaf10 100644 (file)
@@ -234,6 +234,7 @@ static struct {
        {"SGI", "RAID5", "*", BLIST_SPARSELUN},
        {"SGI", "TP9100", "*", BLIST_REPORTLUN2},
        {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+       {"SKhynix", "H28U74301AMR", NULL, BLIST_SKIP_VPD_PAGES},
        {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"SUN", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"DELL", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
index 23ce2f7..26efe12 100644 (file)
@@ -191,9 +191,9 @@ static const struct llcc_slice_config sc8280xp_data[] = {
        { LLCC_CVP,      28, 512,  3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
        { LLCC_APTCM,    30, 1024, 3, 1, 0x0,   0x1, 1, 0, 0, 1, 0, 0 },
        { LLCC_WRCACHE,  31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
-       { LLCC_CVPFW,    32, 512,  1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
-       { LLCC_CPUSS1,   33, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
-       { LLCC_CPUHWT,   36, 512,  1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
+       { LLCC_CVPFW,    17, 512,  1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+       { LLCC_CPUSS1,   3, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+       { LLCC_CPUHWT,   5, 512,  1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
 };
 
 static const struct llcc_slice_config sdm845_data[] =  {
index 2d3ee22..538fa18 100644 (file)
@@ -176,7 +176,8 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
        struct reserved_mem *rmem;
        struct qcom_rmtfs_mem *rmtfs_mem;
        u32 client_id;
-       u32 num_vmids, vmid[NUM_MAX_VMIDS];
+       u32 vmid[NUM_MAX_VMIDS];
+       int num_vmids;
        int ret, i;
 
        rmem = of_reserved_mem_lookup(node);
@@ -228,8 +229,11 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
        }
 
        num_vmids = of_property_count_u32_elems(node, "qcom,vmid");
-       if (num_vmids < 0) {
-               dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", ret);
+       if (num_vmids == -EINVAL) {
+               /* qcom,vmid is optional */
+               num_vmids = 0;
+       } else if (num_vmids < 0) {
+               dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", num_vmids);
                goto remove_cdev;
        } else if (num_vmids > NUM_MAX_VMIDS) {
                dev_warn(&pdev->dev,
index 297dc62..372d647 100644 (file)
@@ -267,35 +267,34 @@ int amdtee_open_session(struct tee_context *ctx,
                goto out;
        }
 
+       /* Open session with loaded TA */
+       handle_open_session(arg, &session_info, param);
+       if (arg->ret != TEEC_SUCCESS) {
+               pr_err("open_session failed %d\n", arg->ret);
+               handle_unload_ta(ta_handle);
+               kref_put(&sess->refcount, destroy_session);
+               goto out;
+       }
+
        /* Find an empty session index for the given TA */
        spin_lock(&sess->lock);
        i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);
-       if (i < TEE_NUM_SESSIONS)
+       if (i < TEE_NUM_SESSIONS) {
+               sess->session_info[i] = session_info;
+               set_session_id(ta_handle, i, &arg->session);
                set_bit(i, sess->sess_mask);
+       }
        spin_unlock(&sess->lock);
 
        if (i >= TEE_NUM_SESSIONS) {
                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
+               handle_close_session(ta_handle, session_info);
                handle_unload_ta(ta_handle);
                kref_put(&sess->refcount, destroy_session);
                rc = -ENOMEM;
                goto out;
        }
 
-       /* Open session with loaded TA */
-       handle_open_session(arg, &session_info, param);
-       if (arg->ret != TEEC_SUCCESS) {
-               pr_err("open_session failed %d\n", arg->ret);
-               spin_lock(&sess->lock);
-               clear_bit(i, sess->sess_mask);
-               spin_unlock(&sess->lock);
-               handle_unload_ta(ta_handle);
-               kref_put(&sess->refcount, destroy_session);
-               goto out;
-       }
-
-       sess->session_info[i] = session_info;
-       set_session_id(ta_handle, i, &arg->session);
 out:
        free_pages((u64)ta, get_order(ta_size));
        return rc;
index 55679fd..566df45 100644 (file)
@@ -613,6 +613,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
        struct thermal_instance *pos;
        struct thermal_zone_device *pos1;
        struct thermal_cooling_device *pos2;
+       bool upper_no_limit;
        int result;
 
        if (trip >= tz->num_trips || trip < 0)
@@ -632,7 +633,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 
        /* lower default 0, upper default max_state */
        lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
-       upper = upper == THERMAL_NO_LIMIT ? cdev->max_state : upper;
+
+       if (upper == THERMAL_NO_LIMIT) {
+               upper = cdev->max_state;
+               upper_no_limit = true;
+       } else {
+               upper_no_limit = false;
+       }
 
        if (lower > upper || upper > cdev->max_state)
                return -EINVAL;
@@ -644,6 +651,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
        dev->cdev = cdev;
        dev->trip = trip;
        dev->upper = upper;
+       dev->upper_no_limit = upper_no_limit;
        dev->lower = lower;
        dev->target = THERMAL_NO_TARGET;
        dev->weight = weight;
@@ -1045,6 +1053,91 @@ devm_thermal_of_cooling_device_register(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_thermal_of_cooling_device_register);
 
+static bool thermal_cooling_device_present(struct thermal_cooling_device *cdev)
+{
+       struct thermal_cooling_device *pos = NULL;
+
+       list_for_each_entry(pos, &thermal_cdev_list, node) {
+               if (pos == cdev)
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * thermal_cooling_device_update - Update a cooling device object
+ * @cdev: Target cooling device.
+ *
+ * Update @cdev to reflect a change of the underlying hardware or platform.
+ *
+ * Must be called when the maximum cooling state of @cdev becomes invalid and so
+ * its .get_max_state() callback needs to be run to produce the new maximum
+ * cooling state value.
+ */
+void thermal_cooling_device_update(struct thermal_cooling_device *cdev)
+{
+       struct thermal_instance *ti;
+       unsigned long state;
+
+       if (IS_ERR_OR_NULL(cdev))
+               return;
+
+       /*
+        * Hold thermal_list_lock throughout the update to prevent the device
+        * from going away while being updated.
+        */
+       mutex_lock(&thermal_list_lock);
+
+       if (!thermal_cooling_device_present(cdev))
+               goto unlock_list;
+
+       /*
+        * Update under the cdev lock to prevent the state from being set beyond
+        * the new limit concurrently.
+        */
+       mutex_lock(&cdev->lock);
+
+       if (cdev->ops->get_max_state(cdev, &cdev->max_state))
+               goto unlock;
+
+       thermal_cooling_device_stats_reinit(cdev);
+
+       list_for_each_entry(ti, &cdev->thermal_instances, cdev_node) {
+               if (ti->upper == cdev->max_state)
+                       continue;
+
+               if (ti->upper < cdev->max_state) {
+                       if (ti->upper_no_limit)
+                               ti->upper = cdev->max_state;
+
+                       continue;
+               }
+
+               ti->upper = cdev->max_state;
+               if (ti->lower > ti->upper)
+                       ti->lower = ti->upper;
+
+               if (ti->target == THERMAL_NO_TARGET)
+                       continue;
+
+               if (ti->target > ti->upper)
+                       ti->target = ti->upper;
+       }
+
+       if (cdev->ops->get_cur_state(cdev, &state) || state > cdev->max_state)
+               goto unlock;
+
+       thermal_cooling_device_stats_update(cdev, state);
+
+unlock:
+       mutex_unlock(&cdev->lock);
+
+unlock_list:
+       mutex_unlock(&thermal_list_lock);
+}
+EXPORT_SYMBOL_GPL(thermal_cooling_device_update);
+
 static void __unbind(struct thermal_zone_device *tz, int mask,
                     struct thermal_cooling_device *cdev)
 {
@@ -1067,20 +1160,17 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
        int i;
        const struct thermal_zone_params *tzp;
        struct thermal_zone_device *tz;
-       struct thermal_cooling_device *pos = NULL;
 
        if (!cdev)
                return;
 
        mutex_lock(&thermal_list_lock);
-       list_for_each_entry(pos, &thermal_cdev_list, node)
-               if (pos == cdev)
-                       break;
-       if (pos != cdev) {
-               /* thermal cooling device not found */
+
+       if (!thermal_cooling_device_present(cdev)) {
                mutex_unlock(&thermal_list_lock);
                return;
        }
+
        list_del(&cdev->node);
 
        /* Unbind all thermal zones associated with 'this' cdev */
@@ -1309,7 +1399,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
                struct thermal_trip trip;
 
                result = thermal_zone_get_trip(tz, count, &trip);
-               if (result)
+               if (result || !trip.temperature)
                        set_bit(count, &tz->trips_disabled);
        }
 
index 7af5438..3d4a787 100644 (file)
@@ -101,6 +101,7 @@ struct thermal_instance {
        struct list_head tz_node; /* node in tz->thermal_instances */
        struct list_head cdev_node; /* node in cdev->thermal_instances */
        unsigned int weight; /* The weight of the cooling device */
+       bool upper_no_limit;
 };
 
 #define to_thermal_zone(_dev) \
@@ -127,6 +128,7 @@ int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
 void thermal_zone_destroy_device_groups(struct thermal_zone_device *);
 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *);
 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev);
+void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev);
 /* used only at binding time */
 ssize_t trip_point_show(struct device *, struct device_attribute *, char *);
 ssize_t weight_show(struct device *, struct device_attribute *, char *);
index cef860d..a4aba7b 100644 (file)
@@ -685,6 +685,8 @@ void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
 {
        struct cooling_dev_stats *stats = cdev->stats;
 
+       lockdep_assert_held(&cdev->lock);
+
        if (!stats)
                return;
 
@@ -706,13 +708,22 @@ static ssize_t total_trans_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
-       int ret;
+       struct cooling_dev_stats *stats;
+       int ret = 0;
+
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats)
+               goto unlock;
 
        spin_lock(&stats->lock);
        ret = sprintf(buf, "%u\n", stats->total_trans);
        spin_unlock(&stats->lock);
 
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return ret;
 }
 
@@ -721,11 +732,18 @@ time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
                      char *buf)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
+       struct cooling_dev_stats *stats;
        ssize_t len = 0;
        int i;
 
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats)
+               goto unlock;
+
        spin_lock(&stats->lock);
+
        update_time_in_state(stats);
 
        for (i = 0; i <= cdev->max_state; i++) {
@@ -734,6 +752,9 @@ time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
        }
        spin_unlock(&stats->lock);
 
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return len;
 }
 
@@ -742,8 +763,16 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
            size_t count)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
-       int i, states = cdev->max_state + 1;
+       struct cooling_dev_stats *stats;
+       int i, states;
+
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats)
+               goto unlock;
+
+       states = cdev->max_state + 1;
 
        spin_lock(&stats->lock);
 
@@ -757,6 +786,9 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
 
        spin_unlock(&stats->lock);
 
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return count;
 }
 
@@ -764,10 +796,18 @@ static ssize_t trans_table_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
+       struct cooling_dev_stats *stats;
        ssize_t len = 0;
        int i, j;
 
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats) {
+               len = -ENODATA;
+               goto unlock;
+       }
+
        len += snprintf(buf + len, PAGE_SIZE - len, " From  :    To\n");
        len += snprintf(buf + len, PAGE_SIZE - len, "       : ");
        for (i = 0; i <= cdev->max_state; i++) {
@@ -775,8 +815,10 @@ static ssize_t trans_table_show(struct device *dev,
                        break;
                len += snprintf(buf + len, PAGE_SIZE - len, "state%2u  ", i);
        }
-       if (len >= PAGE_SIZE)
-               return PAGE_SIZE;
+       if (len >= PAGE_SIZE) {
+               len = PAGE_SIZE;
+               goto unlock;
+       }
 
        len += snprintf(buf + len, PAGE_SIZE - len, "\n");
 
@@ -799,8 +841,12 @@ static ssize_t trans_table_show(struct device *dev,
 
        if (len >= PAGE_SIZE) {
                pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
-               return -EFBIG;
+               len = -EFBIG;
        }
+
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return len;
 }
 
@@ -830,6 +876,8 @@ static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
        unsigned long states = cdev->max_state + 1;
        int var;
 
+       lockdep_assert_held(&cdev->lock);
+
        var = sizeof(*stats);
        var += sizeof(*stats->time_in_state) * states;
        var += sizeof(*stats->trans_table) * states * states;
@@ -855,6 +903,8 @@ out:
 
 static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev)
 {
+       lockdep_assert_held(&cdev->lock);
+
        kfree(cdev->stats);
        cdev->stats = NULL;
 }
@@ -879,6 +929,12 @@ void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
        cooling_device_stats_destroy(cdev);
 }
 
+void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev)
+{
+       cooling_device_stats_destroy(cdev);
+       cooling_device_stats_setup(cdev);
+}
+
 /* these helper will be used only at the time of bindig */
 ssize_t
 trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
index 4339e70..f92ad71 100644 (file)
@@ -942,7 +942,8 @@ static void margining_port_remove(struct tb_port *port)
 
        snprintf(dir_name, sizeof(dir_name), "port%d", port->port);
        parent = debugfs_lookup(dir_name, port->sw->debugfs_dir);
-       debugfs_remove_recursive(debugfs_lookup("margining", parent));
+       if (parent)
+               debugfs_remove_recursive(debugfs_lookup("margining", parent));
 
        kfree(port->usb4->margining);
        port->usb4->margining = NULL;
@@ -967,19 +968,18 @@ static void margining_switch_init(struct tb_switch *sw)
 
 static void margining_switch_remove(struct tb_switch *sw)
 {
+       struct tb_port *upstream, *downstream;
        struct tb_switch *parent_sw;
-       struct tb_port *downstream;
        u64 route = tb_route(sw);
 
        if (!route)
                return;
 
-       /*
-        * Upstream is removed with the router itself but we need to
-        * remove the downstream port margining directory.
-        */
+       upstream = tb_upstream_port(sw);
        parent_sw = tb_switch_parent(sw);
        downstream = tb_port_at(route, parent_sw);
+
+       margining_port_remove(upstream);
        margining_port_remove(downstream);
 }
 
index 4dce2ed..cfebec1 100644 (file)
@@ -46,7 +46,7 @@
 #define QUIRK_AUTO_CLEAR_INT   BIT(0)
 #define QUIRK_E2E              BIT(1)
 
-static int ring_interrupt_index(struct tb_ring *ring)
+static int ring_interrupt_index(const struct tb_ring *ring)
 {
        int bit = ring->hop;
        if (!ring->is_tx)
@@ -63,13 +63,14 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
 {
        int reg = REG_RING_INTERRUPT_BASE +
                  ring_interrupt_index(ring) / 32 * 4;
-       int bit = ring_interrupt_index(ring) & 31;
-       int mask = 1 << bit;
+       int interrupt_bit = ring_interrupt_index(ring) & 31;
+       int mask = 1 << interrupt_bit;
        u32 old, new;
 
        if (ring->irq > 0) {
                u32 step, shift, ivr, misc;
                void __iomem *ivr_base;
+               int auto_clear_bit;
                int index;
 
                if (ring->is_tx)
@@ -77,18 +78,25 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
                else
                        index = ring->hop + ring->nhi->hop_count;
 
-               if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT) {
-                       /*
-                        * Ask the hardware to clear interrupt status
-                        * bits automatically since we already know
-                        * which interrupt was triggered.
-                        */
-                       misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
-                       if (!(misc & REG_DMA_MISC_INT_AUTO_CLEAR)) {
-                               misc |= REG_DMA_MISC_INT_AUTO_CLEAR;
-                               iowrite32(misc, ring->nhi->iobase + REG_DMA_MISC);
-                       }
-               }
+               /*
+                * Intel routers support a bit that isn't part of
+                * the USB4 spec to ask the hardware to clear
+                * interrupt status bits automatically since
+                * we already know which interrupt was triggered.
+                *
+                * Other routers explicitly disable auto-clear
+                * to prevent conditions that may occur where two
+                * MSIX interrupts are simultaneously active and
+                * reading the register clears both of them.
+                */
+               misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
+               if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT)
+                       auto_clear_bit = REG_DMA_MISC_INT_AUTO_CLEAR;
+               else
+                       auto_clear_bit = REG_DMA_MISC_DISABLE_AUTO_CLEAR;
+               if (!(misc & auto_clear_bit))
+                       iowrite32(misc | auto_clear_bit,
+                                 ring->nhi->iobase + REG_DMA_MISC);
 
                ivr_base = ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE;
                step = index / REG_INT_VEC_ALLOC_REGS * REG_INT_VEC_ALLOC_BITS;
@@ -108,7 +116,7 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
 
        dev_dbg(&ring->nhi->pdev->dev,
                "%s interrupt at register %#x bit %d (%#x -> %#x)\n",
-               active ? "enabling" : "disabling", reg, bit, old, new);
+               active ? "enabling" : "disabling", reg, interrupt_bit, old, new);
 
        if (new == old)
                dev_WARN(&ring->nhi->pdev->dev,
@@ -393,14 +401,17 @@ EXPORT_SYMBOL_GPL(tb_ring_poll_complete);
 
 static void ring_clear_msix(const struct tb_ring *ring)
 {
+       int bit;
+
        if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT)
                return;
 
+       bit = ring_interrupt_index(ring) & 31;
        if (ring->is_tx)
-               ioread32(ring->nhi->iobase + REG_RING_NOTIFY_BASE);
+               iowrite32(BIT(bit), ring->nhi->iobase + REG_RING_INT_CLEAR);
        else
-               ioread32(ring->nhi->iobase + REG_RING_NOTIFY_BASE +
-                        4 * (ring->nhi->hop_count / 32));
+               iowrite32(BIT(bit), ring->nhi->iobase + REG_RING_INT_CLEAR +
+                         4 * (ring->nhi->hop_count / 32));
 }
 
 static irqreturn_t ring_msix(int irq, void *data)
index 0d4970d..faef165 100644 (file)
@@ -77,12 +77,13 @@ struct ring_desc {
 
 /*
  * three bitfields: tx, rx, rx overflow
- * Every bitfield contains one bit for every hop (REG_HOP_COUNT). Registers are
- * cleared on read. New interrupts are fired only after ALL registers have been
+ * Every bitfield contains one bit for every hop (REG_HOP_COUNT).
+ * New interrupts are fired only after ALL registers have been
  * read (even those containing only disabled rings).
  */
 #define REG_RING_NOTIFY_BASE   0x37800
 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32)
+#define REG_RING_INT_CLEAR     0x37808
 
 /*
  * two bitfields: rx, tx
@@ -105,6 +106,7 @@ struct ring_desc {
 
 #define REG_DMA_MISC                   0x39864
 #define REG_DMA_MISC_INT_AUTO_CLEAR     BIT(2)
+#define REG_DMA_MISC_DISABLE_AUTO_CLEAR        BIT(17)
 
 #define REG_INMAIL_DATA                        0x39900
 
index b5f2ec7..1157b88 100644 (file)
@@ -20,6 +20,25 @@ static void quirk_dp_credit_allocation(struct tb_switch *sw)
        }
 }
 
+static void quirk_clx_disable(struct tb_switch *sw)
+{
+       sw->quirks |= QUIRK_NO_CLX;
+       tb_sw_dbg(sw, "disabling CL states\n");
+}
+
+static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
+{
+       struct tb_port *port;
+
+       tb_switch_for_each_port(sw, port) {
+               if (!tb_port_is_usb3_down(port))
+                       continue;
+               port->max_bw = 16376;
+               tb_port_dbg(port, "USB3 maximum bandwidth limited to %u Mb/s\n",
+                           port->max_bw);
+       }
+}
+
 struct tb_quirk {
        u16 hw_vendor_id;
        u16 hw_device_id;
@@ -37,6 +56,31 @@ static const struct tb_quirk tb_quirks[] = {
         * DP buffers.
         */
        { 0x8087, 0x0b26, 0x0000, 0x0000, quirk_dp_credit_allocation },
+       /*
+        * Limit the maximum USB3 bandwidth for the following Intel USB4
+        * host routers due to a hardware issue.
+        */
+       { 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI1, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI1, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_MTL_M_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI1, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       /*
+        * CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms.
+        */
+       { 0x0438, 0x0208, 0x0000, 0x0000, quirk_clx_disable },
+       { 0x0438, 0x0209, 0x0000, 0x0000, quirk_clx_disable },
+       { 0x0438, 0x020a, 0x0000, 0x0000, quirk_clx_disable },
+       { 0x0438, 0x020b, 0x0000, 0x0000, quirk_clx_disable },
 };
 
 /**
index 56008eb..9cc2819 100644 (file)
@@ -187,6 +187,22 @@ static ssize_t nvm_authenticate_show(struct device *dev,
        return ret;
 }
 
+static void tb_retimer_set_inbound_sbtx(struct tb_port *port)
+{
+       int i;
+
+       for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
+               usb4_port_retimer_set_inbound_sbtx(port, i);
+}
+
+static void tb_retimer_unset_inbound_sbtx(struct tb_port *port)
+{
+       int i;
+
+       for (i = TB_MAX_RETIMER_INDEX; i >= 1; i--)
+               usb4_port_retimer_unset_inbound_sbtx(port, i);
+}
+
 static ssize_t nvm_authenticate_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -213,6 +229,7 @@ static ssize_t nvm_authenticate_store(struct device *dev,
        rt->auth_status = 0;
 
        if (val) {
+               tb_retimer_set_inbound_sbtx(rt->port);
                if (val == AUTHENTICATE_ONLY) {
                        ret = tb_retimer_nvm_authenticate(rt, true);
                } else {
@@ -232,6 +249,7 @@ static ssize_t nvm_authenticate_store(struct device *dev,
        }
 
 exit_unlock:
+       tb_retimer_unset_inbound_sbtx(rt->port);
        mutex_unlock(&rt->tb->lock);
 exit_rpm:
        pm_runtime_mark_last_busy(&rt->dev);
@@ -440,8 +458,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
         * Enable sideband channel for each retimer. We can do this
         * regardless whether there is device connected or not.
         */
-       for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
-               usb4_port_retimer_set_inbound_sbtx(port, i);
+       tb_retimer_set_inbound_sbtx(port);
 
        /*
         * Before doing anything else, read the authentication status.
@@ -464,6 +481,8 @@ int tb_retimer_scan(struct tb_port *port, bool add)
                        break;
        }
 
+       tb_retimer_unset_inbound_sbtx(port);
+
        if (!last_idx)
                return 0;
 
index 5185cf3..f37a432 100644 (file)
@@ -20,6 +20,7 @@ enum usb4_sb_opcode {
        USB4_SB_OPCODE_ROUTER_OFFLINE = 0x4e45534c,             /* "LSEN" */
        USB4_SB_OPCODE_ENUMERATE_RETIMERS = 0x4d554e45,         /* "ENUM" */
        USB4_SB_OPCODE_SET_INBOUND_SBTX = 0x5055534c,           /* "LSUP" */
+       USB4_SB_OPCODE_UNSET_INBOUND_SBTX = 0x50555355,         /* "USUP" */
        USB4_SB_OPCODE_QUERY_LAST_RETIMER = 0x5453414c,         /* "LAST" */
        USB4_SB_OPCODE_GET_NVM_SECTOR_SIZE = 0x53534e47,        /* "GNSS" */
        USB4_SB_OPCODE_NVM_SET_OFFSET = 0x53504f42,             /* "BOPS" */
index 3370e18..da373ac 100644 (file)
@@ -2968,8 +2968,6 @@ int tb_switch_add(struct tb_switch *sw)
                        dev_warn(&sw->dev, "reading DROM failed: %d\n", ret);
                tb_sw_dbg(sw, "uid: %#llx\n", sw->uid);
 
-               tb_check_quirks(sw);
-
                ret = tb_switch_set_uuid(sw);
                if (ret) {
                        dev_err(&sw->dev, "failed to set UUID\n");
@@ -2988,6 +2986,8 @@ int tb_switch_add(struct tb_switch *sw)
                        }
                }
 
+               tb_check_quirks(sw);
+
                tb_switch_default_link_ports(sw);
 
                ret = tb_switch_update_link_attributes(sw);
index cbb20a2..275ff52 100644 (file)
 #define NVM_MAX_SIZE           SZ_512K
 #define NVM_DATA_DWORDS                16
 
+/* Keep link controller awake during update */
+#define QUIRK_FORCE_POWER_LINK_CONTROLLER              BIT(0)
+/* Disable CLx if not supported */
+#define QUIRK_NO_CLX                                   BIT(1)
+
 /**
  * struct tb_nvm - Structure holding NVM information
  * @dev: Owner of the NVM
@@ -267,6 +272,8 @@ struct tb_bandwidth_group {
  * @group: Bandwidth allocation group the adapter is assigned to. Only
  *        used for DP IN adapters for now.
  * @group_list: The adapter is linked to the group's list of ports through this
+ * @max_bw: Maximum possible bandwidth through this adapter if set to
+ *         non-zero.
  *
  * In USB4 terminology this structure represents an adapter (protocol or
  * lane adapter).
@@ -294,6 +301,7 @@ struct tb_port {
        unsigned int dma_credits;
        struct tb_bandwidth_group *group;
        struct list_head group_list;
+       unsigned int max_bw;
 };
 
 /**
@@ -1019,6 +1027,9 @@ static inline bool tb_switch_is_clx_enabled(const struct tb_switch *sw,
  */
 static inline bool tb_switch_is_clx_supported(const struct tb_switch *sw)
 {
+       if (sw->quirks & QUIRK_NO_CLX)
+               return false;
+
        return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw);
 }
 
@@ -1234,6 +1245,7 @@ int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing,
 int usb4_port_sw_margin_errors(struct tb_port *port, u32 *errors);
 
 int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index);
+int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index);
 int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf,
                           u8 size);
 int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg,
@@ -1291,9 +1303,6 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port);
 void usb4_port_device_remove(struct usb4_port *usb4);
 int usb4_port_device_resume(struct usb4_port *usb4);
 
-/* Keep link controller awake during update */
-#define QUIRK_FORCE_POWER_LINK_CONTROLLER              BIT(0)
-
 void tb_check_quirks(struct tb_switch *sw);
 
 #ifdef CONFIG_ACPI
index 1e5e9c1..a0996cb 100644 (file)
@@ -1579,6 +1579,20 @@ int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index)
 }
 
 /**
+ * usb4_port_retimer_unset_inbound_sbtx() - Disable sideband channel transactions
+ * @port: USB4 port
+ * @index: Retimer index
+ *
+ * Disables sideband channel transations on SBTX. The reverse of
+ * usb4_port_retimer_set_inbound_sbtx().
+ */
+int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index)
+{
+       return usb4_port_retimer_op(port, index,
+                                   USB4_SB_OPCODE_UNSET_INBOUND_SBTX, 500);
+}
+
+/**
  * usb4_port_retimer_read() - Read from retimer sideband registers
  * @port: USB4 port
  * @index: Retimer index
@@ -1868,6 +1882,15 @@ int usb4_port_retimer_nvm_read(struct tb_port *port, u8 index,
                                usb4_port_retimer_nvm_read_block, &info);
 }
 
+static inline unsigned int
+usb4_usb3_port_max_bandwidth(const struct tb_port *port, unsigned int bw)
+{
+       /* Take the possible bandwidth limitation into account */
+       if (port->max_bw)
+               return min(bw, port->max_bw);
+       return bw;
+}
+
 /**
  * usb4_usb3_port_max_link_rate() - Maximum support USB3 link rate
  * @port: USB3 adapter port
@@ -1889,7 +1912,9 @@ int usb4_usb3_port_max_link_rate(struct tb_port *port)
                return ret;
 
        lr = (val & ADP_USB3_CS_4_MSLR_MASK) >> ADP_USB3_CS_4_MSLR_SHIFT;
-       return lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000;
+       ret = lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000;
+
+       return usb4_usb3_port_max_bandwidth(port, ret);
 }
 
 /**
@@ -1916,7 +1941,9 @@ int usb4_usb3_port_actual_link_rate(struct tb_port *port)
                return 0;
 
        lr = val & ADP_USB3_CS_4_ALR_MASK;
-       return lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000;
+       ret = lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000;
+
+       return usb4_usb3_port_max_bandwidth(port, ret);
 }
 
 static int usb4_usb3_port_cm_request(struct tb_port *port, bool request)
@@ -2067,18 +2094,30 @@ static int usb4_usb3_port_write_allocated_bandwidth(struct tb_port *port,
                                                    int downstream_bw)
 {
        u32 val, ubw, dbw, scale;
-       int ret;
+       int ret, max_bw;
 
-       /* Read the used scale, hardware default is 0 */
-       ret = tb_port_read(port, &scale, TB_CFG_PORT,
-                          port->cap_adap + ADP_USB3_CS_3, 1);
+       /* Figure out suitable scale */
+       scale = 0;
+       max_bw = max(upstream_bw, downstream_bw);
+       while (scale < 64) {
+               if (mbps_to_usb3_bw(max_bw, scale) < 4096)
+                       break;
+               scale++;
+       }
+
+       if (WARN_ON(scale >= 64))
+               return -EINVAL;
+
+       ret = tb_port_write(port, &scale, TB_CFG_PORT,
+                           port->cap_adap + ADP_USB3_CS_3, 1);
        if (ret)
                return ret;
 
-       scale &= ADP_USB3_CS_3_SCALE_MASK;
        ubw = mbps_to_usb3_bw(upstream_bw, scale);
        dbw = mbps_to_usb3_bw(downstream_bw, scale);
 
+       tb_port_dbg(port, "scaled bandwidth %u/%u, scale %u\n", ubw, dbw, scale);
+
        ret = tb_port_read(port, &val, TB_CFG_PORT,
                           port->cap_adap + ADP_USB3_CS_2, 1);
        if (ret)
index 5bddb2f..98764e7 100644 (file)
@@ -43,6 +43,7 @@ struct xencons_info {
        int irq;
        int vtermno;
        grant_ref_t gntref;
+       spinlock_t ring_lock;
 };
 
 static LIST_HEAD(xenconsoles);
@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons,
        XENCONS_RING_IDX cons, prod;
        struct xencons_interface *intf = xencons->intf;
        int sent = 0;
+       unsigned long flags;
 
+       spin_lock_irqsave(&xencons->ring_lock, flags);
        cons = intf->out_cons;
        prod = intf->out_prod;
        mb();                   /* update queue values before going on */
 
        if ((prod - cons) > sizeof(intf->out)) {
+               spin_unlock_irqrestore(&xencons->ring_lock, flags);
                pr_err_once("xencons: Illegal ring page indices");
                return -EINVAL;
        }
@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons,
 
        wmb();                  /* write ring before updating pointer */
        intf->out_prod = prod;
+       spin_unlock_irqrestore(&xencons->ring_lock, flags);
 
        if (sent)
                notify_daemon(xencons);
@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
        int recv = 0;
        struct xencons_info *xencons = vtermno_to_xencons(vtermno);
        unsigned int eoiflag = 0;
+       unsigned long flags;
 
        if (xencons == NULL)
                return -EINVAL;
        intf = xencons->intf;
 
+       spin_lock_irqsave(&xencons->ring_lock, flags);
        cons = intf->in_cons;
        prod = intf->in_prod;
        mb();                   /* get pointers before reading ring */
 
        if ((prod - cons) > sizeof(intf->in)) {
+               spin_unlock_irqrestore(&xencons->ring_lock, flags);
                pr_err_once("xencons: Illegal ring page indices");
                return -EINVAL;
        }
@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
                xencons->out_cons = intf->out_cons;
                xencons->out_cons_same = 0;
        }
+       if (!recv && xencons->out_cons_same++ > 1) {
+               eoiflag = XEN_EOI_FLAG_SPURIOUS;
+       }
+       spin_unlock_irqrestore(&xencons->ring_lock, flags);
+
        if (recv) {
                notify_daemon(xencons);
-       } else if (xencons->out_cons_same++ > 1) {
-               eoiflag = XEN_EOI_FLAG_SPURIOUS;
        }
 
        xen_irq_lateeoi(xencons->irq, eoiflag);
@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void)
                info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
                if (!info)
                        return -ENOMEM;
+               spin_lock_init(&info->ring_lock);
        } else if (info->intf != NULL) {
                /* already configured */
                return 0;
@@ -275,6 +287,7 @@ err:
 
 static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
 {
+       spin_lock_init(&info->ring_lock);
        info->evtchn = xen_start_info->console.domU.evtchn;
        /* GFN == MFN for PV guest */
        info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void)
                info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
                if (!info)
                        return -ENOMEM;
+               spin_lock_init(&info->ring_lock);
        }
 
        info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
@@ -482,6 +496,7 @@ static int xencons_probe(struct xenbus_device *dev,
        info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
+       spin_lock_init(&info->ring_lock);
        dev_set_drvdata(&dev->dev, info);
        info->xbdev = dev;
        info->vtermno = xenbus_devid_to_vtermno(devid);
index deeea61..1f6320d 100644 (file)
@@ -60,6 +60,11 @@ static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev)
                        return NULL;
        }
 
+       if (func->devfn != PCI_DEV_FN_HOST_DEVICE &&
+           func->devfn != PCI_DEV_FN_OTG) {
+               return NULL;
+       }
+
        return func;
 }
 
index 9b8325f..d63d5d9 100644 (file)
@@ -403,20 +403,6 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
        case USB_REQ_SET_ISOCH_DELAY:
                ret = cdnsp_ep0_set_isoch_delay(pdev, ctrl);
                break;
-       case USB_REQ_SET_INTERFACE:
-               /*
-                * Add request into pending list to block sending status stage
-                * by libcomposite.
-                */
-               list_add_tail(&pdev->ep0_preq.list,
-                             &pdev->ep0_preq.pep->pending_list);
-
-               ret = cdnsp_ep0_delegate_req(pdev, ctrl);
-               if (ret == -EBUSY)
-                       ret = 0;
-
-               list_del(&pdev->ep0_preq.list);
-               break;
        default:
                ret = cdnsp_ep0_delegate_req(pdev, ctrl);
                break;
@@ -474,9 +460,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
        else
                ret = cdnsp_ep0_delegate_req(pdev, ctrl);
 
-       if (!len)
-               pdev->ep0_stage = CDNSP_STATUS_STAGE;
-
        if (ret == USB_GADGET_DELAYED_STATUS) {
                trace_cdnsp_ep0_status_stage("delayed");
                return;
@@ -484,6 +467,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
 out:
        if (ret < 0)
                cdnsp_ep0_stall(pdev);
-       else if (pdev->ep0_stage == CDNSP_STATUS_STAGE)
+       else if (!len && pdev->ep0_stage != CDNSP_STATUS_STAGE)
                cdnsp_status_stage(pdev);
 }
index efd54ed..7b151f5 100644 (file)
 #define PLAT_DRIVER_NAME       "cdns-usbssp"
 
 #define CDNS_VENDOR_ID         0x17cd
-#define CDNS_DEVICE_ID         0x0100
+#define CDNS_DEVICE_ID         0x0200
+#define CDNS_DRD_ID            0x0100
 #define CDNS_DRD_IF            (PCI_CLASS_SERIAL_USB << 8 | 0x80)
 
 static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
 {
-       struct pci_dev *func;
-
        /*
         * Gets the second function.
-        * It's little tricky, but this platform has two function.
-        * The fist keeps resources for Host/Device while the second
-        * keeps resources for DRD/OTG.
+        * Platform has two function. The fist keeps resources for
+        * Host/Device while the secon keeps resources for DRD/OTG.
         */
-       func = pci_get_device(pdev->vendor, pdev->device, NULL);
-       if (!func)
-               return NULL;
+       if (pdev->device == CDNS_DEVICE_ID)
+               return  pci_get_device(pdev->vendor, CDNS_DRD_ID, NULL);
+       else if (pdev->device == CDNS_DRD_ID)
+               return pci_get_device(pdev->vendor, CDNS_DEVICE_ID, NULL);
 
-       if (func->devfn == pdev->devfn) {
-               func = pci_get_device(pdev->vendor, pdev->device, func);
-               if (!func)
-                       return NULL;
-       }
-
-       return func;
+       return NULL;
 }
 
 static int cdnsp_pci_probe(struct pci_dev *pdev,
@@ -230,6 +223,8 @@ static const struct pci_device_id cdnsp_pci_ids[] = {
          PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID },
        { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
          CDNS_DRD_IF, PCI_ANY_ID },
+       { PCI_VENDOR_ID_CDNS, CDNS_DRD_ID, PCI_ANY_ID, PCI_ANY_ID,
+         CDNS_DRD_IF, PCI_ANY_ID },
        { 0, }
 };
 
index 005c67c..f210b74 100644 (file)
@@ -208,6 +208,7 @@ struct hw_bank {
  * @in_lpm: if the core in low power mode
  * @wakeup_int: if wakeup interrupt occur
  * @rev: The revision number for controller
+ * @mutex: protect code from concorrent running when doing role switch
  */
 struct ci_hdrc {
        struct device                   *dev;
@@ -260,6 +261,7 @@ struct ci_hdrc {
        bool                            in_lpm;
        bool                            wakeup_int;
        enum ci_revision                rev;
+       struct mutex                    mutex;
 };
 
 static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
index 27c6012..281fc51 100644 (file)
@@ -984,9 +984,16 @@ static ssize_t role_store(struct device *dev,
                             strlen(ci->roles[role]->name)))
                        break;
 
-       if (role == CI_ROLE_END || role == ci->role)
+       if (role == CI_ROLE_END)
                return -EINVAL;
 
+       mutex_lock(&ci->mutex);
+
+       if (role == ci->role) {
+               mutex_unlock(&ci->mutex);
+               return n;
+       }
+
        pm_runtime_get_sync(dev);
        disable_irq(ci->irq);
        ci_role_stop(ci);
@@ -995,6 +1002,7 @@ static ssize_t role_store(struct device *dev,
                ci_handle_vbus_change(ci);
        enable_irq(ci->irq);
        pm_runtime_put_sync(dev);
+       mutex_unlock(&ci->mutex);
 
        return (ret == 0) ? n : ret;
 }
@@ -1030,6 +1038,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        spin_lock_init(&ci->lock);
+       mutex_init(&ci->mutex);
        ci->dev = dev;
        ci->platdata = dev_get_platdata(dev);
        ci->imx28_write_fix = !!(ci->platdata->flags &
index 622c3b6..f5490f2 100644 (file)
@@ -167,8 +167,10 @@ static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
 
 void ci_handle_id_switch(struct ci_hdrc *ci)
 {
-       enum ci_role role = ci_otg_role(ci);
+       enum ci_role role;
 
+       mutex_lock(&ci->mutex);
+       role = ci_otg_role(ci);
        if (role != ci->role) {
                dev_dbg(ci->dev, "switching from %s to %s\n",
                        ci_role(ci)->name, ci->roles[role]->name);
@@ -198,6 +200,7 @@ void ci_handle_id_switch(struct ci_hdrc *ci)
                if (role == CI_ROLE_GADGET)
                        ci_handle_vbus_change(ci);
        }
+       mutex_unlock(&ci->mutex);
 }
 /**
  * ci_otg_work - perform otg (vbus/id) event handle
index d8d6493..a8605b0 100644 (file)
@@ -35,7 +35,8 @@ static void dwc2_ovr_init(struct dwc2_hsotg *hsotg)
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
-       dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST));
+       dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST) ||
+                               (hsotg->role_sw_default_mode == USB_DR_MODE_HOST));
 }
 
 static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid)
index 62fa637..8b15742 100644 (file)
@@ -4549,8 +4549,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
        hsotg->gadget.dev.of_node = hsotg->dev->of_node;
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
-       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL ||
-           (hsotg->dr_mode == USB_DR_MODE_OTG && dwc2_is_device_mode(hsotg))) {
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
                ret = dwc2_lowlevel_hw_enable(hsotg);
                if (ret)
                        goto err;
@@ -4612,8 +4611,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
        if (!IS_ERR_OR_NULL(hsotg->uphy))
                otg_set_peripheral(hsotg->uphy->otg, NULL);
 
-       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL ||
-           (hsotg->dr_mode == USB_DR_MODE_OTG && dwc2_is_device_mode(hsotg)))
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
                dwc2_lowlevel_hw_disable(hsotg);
 
        return 0;
index 23ef759..d1589ba 100644 (file)
@@ -91,13 +91,6 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg)
        return 0;
 }
 
-static void __dwc2_disable_regulators(void *data)
-{
-       struct dwc2_hsotg *hsotg = data;
-
-       regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-}
-
 static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
 {
        struct platform_device *pdev = to_platform_device(hsotg->dev);
@@ -108,11 +101,6 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
        if (ret)
                return ret;
 
-       ret = devm_add_action_or_reset(&pdev->dev,
-                                      __dwc2_disable_regulators, hsotg);
-       if (ret)
-               return ret;
-
        if (hsotg->clk) {
                ret = clk_prepare_enable(hsotg->clk);
                if (ret)
@@ -168,7 +156,7 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
        if (hsotg->clk)
                clk_disable_unprepare(hsotg->clk);
 
-       return 0;
+       return regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 }
 
 /**
@@ -576,8 +564,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
        dwc2_debugfs_init(hsotg);
 
        /* Gadget code manages lowlevel hw on its own */
-       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL ||
-           (hsotg->dr_mode == USB_DR_MODE_OTG && dwc2_is_device_mode(hsotg)))
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
                dwc2_lowlevel_hw_disable(hsotg);
 
 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
@@ -608,7 +595,7 @@ error_init:
        if (hsotg->params.activate_stm_id_vb_detection)
                regulator_disable(hsotg->usb33d);
 error:
-       if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL)
+       if (hsotg->ll_hw_enabled)
                dwc2_lowlevel_hw_disable(hsotg);
        return retval;
 }
index 582ebd9..4743e91 100644 (file)
@@ -1098,7 +1098,7 @@ struct dwc3_scratchpad_array {
  *                     change quirk.
  * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate
  *                     check during HS transmit.
- * @resume-hs-terminations: Set if we enable quirk for fixing improper crc
+ * @resume_hs_terminations: Set if we enable quirk for fixing improper crc
  *                     generation after resume from suspend.
  * @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed
  *                     instances in park mode.
index 3c63fa9..cf5b4f4 100644 (file)
@@ -1699,6 +1699,7 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
  */
 static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
 {
+       struct dwc3 *dwc = dep->dwc;
        struct dwc3_gadget_ep_cmd_params params;
        u32 cmd;
        int ret;
@@ -1722,10 +1723,13 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
 
-       if (!interrupt)
+       if (!interrupt) {
+               if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A))
+                       mdelay(1);
                dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-       else if (!ret)
+       } else if (!ret) {
                dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+       }
 
        dep->flags &= ~DWC3_EP_DELAY_STOP;
        return ret;
@@ -3774,7 +3778,11 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
         * enabled, the EndTransfer command will have completed upon
         * returning from this function.
         *
-        * This mode is NOT available on the DWC_usb31 IP.
+        * This mode is NOT available on the DWC_usb31 IP.  In this
+        * case, if the IOC bit is not set, then delay by 1ms
+        * after issuing the EndTransfer command.  This allows for the
+        * controller to handle the command completely before DWC3
+        * remove requests attempts to unmap USB request buffers.
         */
 
        __dwc3_stop_active_transfer(dep, force, interrupt);
index fa7dd6c..5377d87 100644 (file)
@@ -2079,10 +2079,9 @@ unknown:
                                sizeof(url_descriptor->URL)
                                - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_offset);
 
-                       if (ctrl->wLength < WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH
-                                           + landing_page_length)
-                               landing_page_length = ctrl->wLength
-                                       - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_offset;
+                       if (w_length < WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_length)
+                               landing_page_length = w_length
+                               - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_offset;
 
                        memcpy(url_descriptor->URL,
                                cdev->landing_page + landing_page_offset,
index c1f62e9..4a42574 100644 (file)
@@ -1422,7 +1422,7 @@ void g_audio_cleanup(struct g_audio *g_audio)
        uac = g_audio->uac;
        card = uac->card;
        if (card)
-               snd_card_free(card);
+               snd_card_free_when_closed(card);
 
        kfree(uac->p_prm.reqs);
        kfree(uac->c_prm.reqs);
index 5402e4b..12fc6eb 100644 (file)
@@ -410,6 +410,7 @@ static const struct usb_device_id onboard_hub_id_table[] = {
        { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 */
        { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 */
        { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */
index 0a943a1..aca5f50 100644 (file)
@@ -36,6 +36,7 @@ static const struct onboard_hub_pdata vialab_vl817_data = {
 
 static const struct of_device_id onboard_hub_match[] = {
        { .compatible = "usb424,2514", .data = &microchip_usb424_data, },
+       { .compatible = "usb424,2517", .data = &microchip_usb424_data, },
        { .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
        { .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
        { .compatible = "usb5e3,608", .data = &genesys_gl850g_data, },
index c7b763d..1f8c9b1 100644 (file)
@@ -111,6 +111,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_BROKEN_FUA),
 
+/* Reported by: Yaroslav Furman <yaro330@gmail.com> */
+UNUSUAL_DEV(0x152d, 0x0583, 0x0000, 0x9999,
+               "JMicron",
+               "JMS583Gen 2",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_REPORT_OPCODES),
+
 /* Reported-by: Thinh Nguyen <thinhn@synopsys.com> */
 UNUSUAL_DEV(0x154b, 0xf00b, 0x0000, 0x9999,
                "PNY",
index a0d943d..1ee774c 100644 (file)
@@ -1445,10 +1445,18 @@ static int tcpm_ams_start(struct tcpm_port *port, enum tcpm_ams ams)
 static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
                           const u32 *data, int cnt)
 {
+       u32 vdo_hdr = port->vdo_data[0];
+
        WARN_ON(!mutex_is_locked(&port->lock));
 
-       /* Make sure we are not still processing a previous VDM packet */
-       WARN_ON(port->vdm_state > VDM_STATE_DONE);
+       /* If is sending discover_identity, handle received message first */
+       if (PD_VDO_SVDM(vdo_hdr) && PD_VDO_CMD(vdo_hdr) == CMD_DISCOVER_IDENT) {
+               port->send_discover = true;
+               mod_send_discover_delayed_work(port, SEND_DISCOVER_RETRY_MS);
+       } else {
+               /* Make sure we are not still processing a previous VDM packet */
+               WARN_ON(port->vdm_state > VDM_STATE_DONE);
+       }
 
        port->vdo_count = cnt + 1;
        port->vdo_data[0] = header;
@@ -1948,11 +1956,13 @@ static void vdm_run_state_machine(struct tcpm_port *port)
                        switch (PD_VDO_CMD(vdo_hdr)) {
                        case CMD_DISCOVER_IDENT:
                                res = tcpm_ams_start(port, DISCOVER_IDENTITY);
-                               if (res == 0)
+                               if (res == 0) {
                                        port->send_discover = false;
-                               else if (res == -EAGAIN)
+                               } else if (res == -EAGAIN) {
+                                       port->vdo_data[0] = 0;
                                        mod_send_discover_delayed_work(port,
                                                                       SEND_DISCOVER_RETRY_MS);
+                               }
                                break;
                        case CMD_DISCOVER_SVID:
                                res = tcpm_ams_start(port, DISCOVER_SVIDS);
@@ -2035,6 +2045,7 @@ static void vdm_run_state_machine(struct tcpm_port *port)
                        unsigned long timeout;
 
                        port->vdm_retries = 0;
+                       port->vdo_data[0] = 0;
                        port->vdm_state = VDM_STATE_BUSY;
                        timeout = vdm_ready_timeout(vdo_hdr);
                        mod_vdm_delayed_work(port, timeout);
@@ -4570,6 +4581,9 @@ static void run_state_machine(struct tcpm_port *port)
        case SOFT_RESET:
                port->message_id = 0;
                port->rx_msgid = -1;
+               /* remove existing capabilities */
+               usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+               port->partner_source_caps = NULL;
                tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
                tcpm_ams_finish(port);
                if (port->pwr_role == TYPEC_SOURCE) {
@@ -4589,6 +4603,9 @@ static void run_state_machine(struct tcpm_port *port)
        case SOFT_RESET_SEND:
                port->message_id = 0;
                port->rx_msgid = -1;
+               /* remove existing capabilities */
+               usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+               port->partner_source_caps = NULL;
                if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
                        tcpm_set_state_cond(port, hard_reset_state(port), 0);
                else
@@ -4718,6 +4735,9 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_state(port, SNK_STARTUP, 0);
                break;
        case PR_SWAP_SNK_SRC_SINK_OFF:
+               /* will be source, remove existing capabilities */
+               usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+               port->partner_source_caps = NULL;
                /*
                 * Prevent vbus discharge circuit from turning on during PR_SWAP
                 * as this is not a disconnect.
index f632350..8d1baf2 100644 (file)
@@ -1125,12 +1125,11 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
        return NULL;
 }
 
-static int ucsi_register_port(struct ucsi *ucsi, int index)
+static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
 {
        struct usb_power_delivery_desc desc = { ucsi->cap.pd_version};
        struct usb_power_delivery_capabilities_desc pd_caps;
        struct usb_power_delivery_capabilities *pd_cap;
-       struct ucsi_connector *con = &ucsi->connector[index];
        struct typec_capability *cap = &con->typec_cap;
        enum typec_accessory *accessory = cap->accessory;
        enum usb_role u_role = USB_ROLE_NONE;
@@ -1151,7 +1150,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
        init_completion(&con->complete);
        mutex_init(&con->lock);
        INIT_LIST_HEAD(&con->partner_tasks);
-       con->num = index + 1;
        con->ucsi = ucsi;
 
        cap->fwnode = ucsi_find_fwnode(con);
@@ -1328,8 +1326,8 @@ out_unlock:
  */
 static int ucsi_init(struct ucsi *ucsi)
 {
-       struct ucsi_connector *con;
-       u64 command;
+       struct ucsi_connector *con, *connector;
+       u64 command, ntfy;
        int ret;
        int i;
 
@@ -1341,8 +1339,8 @@ static int ucsi_init(struct ucsi *ucsi)
        }
 
        /* Enable basic notifications */
-       ucsi->ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
-       command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
+       ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
+       command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
        ret = ucsi_send_command(ucsi, command, NULL, 0);
        if (ret < 0)
                goto err_reset;
@@ -1359,31 +1357,33 @@ static int ucsi_init(struct ucsi *ucsi)
        }
 
        /* Allocate the connectors. Released in ucsi_unregister() */
-       ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
-                                 sizeof(*ucsi->connector), GFP_KERNEL);
-       if (!ucsi->connector) {
+       connector = kcalloc(ucsi->cap.num_connectors + 1, sizeof(*connector), GFP_KERNEL);
+       if (!connector) {
                ret = -ENOMEM;
                goto err_reset;
        }
 
        /* Register all connectors */
        for (i = 0; i < ucsi->cap.num_connectors; i++) {
-               ret = ucsi_register_port(ucsi, i);
+               connector[i].num = i + 1;
+               ret = ucsi_register_port(ucsi, &connector[i]);
                if (ret)
                        goto err_unregister;
        }
 
        /* Enable all notifications */
-       ucsi->ntfy = UCSI_ENABLE_NTFY_ALL;
-       command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
+       ntfy = UCSI_ENABLE_NTFY_ALL;
+       command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
        ret = ucsi_send_command(ucsi, command, NULL, 0);
        if (ret < 0)
                goto err_unregister;
 
+       ucsi->connector = connector;
+       ucsi->ntfy = ntfy;
        return 0;
 
 err_unregister:
-       for (con = ucsi->connector; con->port; con++) {
+       for (con = connector; con->port; con++) {
                ucsi_unregister_partner(con);
                ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
                ucsi_unregister_port_psy(con);
@@ -1399,10 +1399,7 @@ err_unregister:
                typec_unregister_port(con->port);
                con->port = NULL;
        }
-
-       kfree(ucsi->connector);
-       ucsi->connector = NULL;
-
+       kfree(connector);
 err_reset:
        memset(&ucsi->cap, 0, sizeof(ucsi->cap));
        ucsi_reset_ppm(ucsi);
index ce0c8ef..62206a6 100644 (file)
@@ -78,7 +78,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
        if (ret)
                goto out_clear_bit;
 
-       if (!wait_for_completion_timeout(&ua->complete, HZ))
+       if (!wait_for_completion_timeout(&ua->complete, 5 * HZ))
                ret = -ETIMEDOUT;
 
 out_clear_bit:
index e897537..d95fd38 100644 (file)
@@ -442,16 +442,10 @@ static long mlx5vf_precopy_ioctl(struct file *filp, unsigned int cmd,
        if (migf->pre_copy_initial_bytes > *pos) {
                info.initial_bytes = migf->pre_copy_initial_bytes - *pos;
        } else {
-               buf = mlx5vf_get_data_buff_from_pos(migf, *pos, &end_of_data);
-               if (buf) {
-                       info.dirty_bytes = buf->start_pos + buf->length - *pos;
-               } else {
-                       if (!end_of_data) {
-                               ret = -EINVAL;
-                               goto err_migf_unlock;
-                       }
-                       info.dirty_bytes = inc_length;
-               }
+               info.dirty_bytes = migf->max_pos - *pos;
+               if (!info.dirty_bytes)
+                       end_of_data = true;
+               info.dirty_bytes += inc_length;
        }
 
        if (!end_of_data || !inc_length) {
index 0ef8b89..5fc670c 100644 (file)
@@ -1175,14 +1175,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                        < block_group->zone_unusable);
                WARN_ON(block_group->space_info->disk_total
                        < block_group->length * factor);
-               WARN_ON(test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE,
-                                &block_group->runtime_flags) &&
-                       block_group->space_info->active_total_bytes
-                       < block_group->length);
        }
        block_group->space_info->total_bytes -= block_group->length;
-       if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags))
-               block_group->space_info->active_total_bytes -= block_group->length;
        block_group->space_info->bytes_readonly -=
                (block_group->length - block_group->zone_unusable);
        block_group->space_info->bytes_zone_unusable -=
@@ -3476,6 +3470,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
        spin_unlock(&info->delalloc_root_lock);
 
        while (total) {
+               struct btrfs_space_info *space_info;
                bool reclaim = false;
 
                cache = btrfs_lookup_block_group(info, bytenr);
@@ -3483,6 +3478,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                        ret = -ENOENT;
                        break;
                }
+               space_info = cache->space_info;
                factor = btrfs_bg_type_to_factor(cache->flags);
 
                /*
@@ -3497,7 +3493,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                byte_in_group = bytenr - cache->start;
                WARN_ON(byte_in_group > cache->length);
 
-               spin_lock(&cache->space_info->lock);
+               spin_lock(&space_info->lock);
                spin_lock(&cache->lock);
 
                if (btrfs_test_opt(info, SPACE_CACHE) &&
@@ -3510,24 +3506,24 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                        old_val += num_bytes;
                        cache->used = old_val;
                        cache->reserved -= num_bytes;
-                       cache->space_info->bytes_reserved -= num_bytes;
-                       cache->space_info->bytes_used += num_bytes;
-                       cache->space_info->disk_used += num_bytes * factor;
+                       space_info->bytes_reserved -= num_bytes;
+                       space_info->bytes_used += num_bytes;
+                       space_info->disk_used += num_bytes * factor;
                        spin_unlock(&cache->lock);
-                       spin_unlock(&cache->space_info->lock);
+                       spin_unlock(&space_info->lock);
                } else {
                        old_val -= num_bytes;
                        cache->used = old_val;
                        cache->pinned += num_bytes;
-                       btrfs_space_info_update_bytes_pinned(info,
-                                       cache->space_info, num_bytes);
-                       cache->space_info->bytes_used -= num_bytes;
-                       cache->space_info->disk_used -= num_bytes * factor;
+                       btrfs_space_info_update_bytes_pinned(info, space_info,
+                                                            num_bytes);
+                       space_info->bytes_used -= num_bytes;
+                       space_info->disk_used -= num_bytes * factor;
 
                        reclaim = should_reclaim_block_group(cache, num_bytes);
 
                        spin_unlock(&cache->lock);
-                       spin_unlock(&cache->space_info->lock);
+                       spin_unlock(&space_info->lock);
 
                        set_extent_dirty(&trans->transaction->pinned_extents,
                                         bytenr, bytenr + num_bytes - 1,
index 0d250d0..d84cef8 100644 (file)
@@ -2693,8 +2693,13 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
                bg_reclaim_threshold = READ_ONCE(sinfo->bg_reclaim_threshold);
 
        spin_lock(&ctl->tree_lock);
+       /* Count initial region as zone_unusable until it gets activated. */
        if (!used)
                to_free = size;
+       else if (initial &&
+                test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &block_group->fs_info->flags) &&
+                (block_group->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM)))
+               to_free = 0;
        else if (initial)
                to_free = block_group->zone_capacity;
        else if (offset >= block_group->alloc_offset)
@@ -2722,7 +2727,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
        reclaimable_unusable = block_group->zone_unusable -
                               (block_group->length - block_group->zone_capacity);
        /* All the region is now unusable. Mark it as unused and reclaim */
-       if (block_group->zone_unusable == block_group->length) {
+       if (block_group->zone_unusable == block_group->length &&
+           block_group->alloc_offset) {
                btrfs_mark_bg_unused(block_group);
        } else if (bg_reclaim_threshold &&
                   reclaimable_unusable >=
index 4c477ea..24cd492 100644 (file)
@@ -120,11 +120,8 @@ enum {
        /* Indicate that we want to commit the transaction. */
        BTRFS_FS_NEED_TRANS_COMMIT,
 
-       /*
-        * Indicate metadata over-commit is disabled. This is set when active
-        * zone tracking is needed.
-        */
-       BTRFS_FS_NO_OVERCOMMIT,
+       /* This is set when active zone tracking is needed. */
+       BTRFS_FS_ACTIVE_ZONE_TRACKING,
 
        /*
         * Indicate if we have some features changed, this is mostly for
index 6c18dc9..957e4d7 100644 (file)
@@ -5421,8 +5421,13 @@ static int btrfs_inode_by_name(struct btrfs_inode *dir, struct dentry *dentry,
                return -ENOMEM;
 
        ret = fscrypt_setup_filename(&dir->vfs_inode, &dentry->d_name, 1, &fname);
-       if (ret)
+       if (ret < 0)
                goto out;
+       /*
+        * fscrypt_setup_filename() should never return a positive value, but
+        * gcc on sparc/parisc thinks it can, so assert that doesn't happen.
+        */
+       ASSERT(ret == 0);
 
        /* This needs to handle no-key deletions later on */
 
index 69c0950..3eecce8 100644 (file)
@@ -308,8 +308,6 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,
        ASSERT(found);
        spin_lock(&found->lock);
        found->total_bytes += block_group->length;
-       if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags))
-               found->active_total_bytes += block_group->length;
        found->disk_total += block_group->length * factor;
        found->bytes_used += block_group->used;
        found->disk_used += block_group->used * factor;
@@ -379,22 +377,6 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
        return avail;
 }
 
-static inline u64 writable_total_bytes(struct btrfs_fs_info *fs_info,
-                                      struct btrfs_space_info *space_info)
-{
-       /*
-        * On regular filesystem, all total_bytes are always writable. On zoned
-        * filesystem, there may be a limitation imposed by max_active_zones.
-        * For metadata allocation, we cannot finish an existing active block
-        * group to avoid a deadlock. Thus, we need to consider only the active
-        * groups to be writable for metadata space.
-        */
-       if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
-               return space_info->total_bytes;
-
-       return space_info->active_total_bytes;
-}
-
 int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
                         struct btrfs_space_info *space_info, u64 bytes,
                         enum btrfs_reserve_flush_enum flush)
@@ -407,13 +389,13 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
                return 0;
 
        used = btrfs_space_info_used(space_info, true);
-       if (test_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags) &&
+       if (test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags) &&
            (space_info->flags & BTRFS_BLOCK_GROUP_METADATA))
                avail = 0;
        else
                avail = calc_available_free_space(fs_info, space_info, flush);
 
-       if (used + bytes < writable_total_bytes(fs_info, space_info) + avail)
+       if (used + bytes < space_info->total_bytes + avail)
                return 1;
        return 0;
 }
@@ -449,7 +431,7 @@ again:
                ticket = list_first_entry(head, struct reserve_ticket, list);
 
                /* Check and see if our ticket can be satisfied now. */
-               if ((used + ticket->bytes <= writable_total_bytes(fs_info, space_info)) ||
+               if ((used + ticket->bytes <= space_info->total_bytes) ||
                    btrfs_can_overcommit(fs_info, space_info, ticket->bytes,
                                         flush)) {
                        btrfs_space_info_update_bytes_may_use(fs_info,
@@ -829,7 +811,6 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
 {
        u64 used;
        u64 avail;
-       u64 total;
        u64 to_reclaim = space_info->reclaim_size;
 
        lockdep_assert_held(&space_info->lock);
@@ -844,9 +825,8 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
         * space.  If that's the case add in our overage so we make sure to put
         * appropriate pressure on the flushing state machine.
         */
-       total = writable_total_bytes(fs_info, space_info);
-       if (total + avail < used)
-               to_reclaim += used - (total + avail);
+       if (space_info->total_bytes + avail < used)
+               to_reclaim += used - (space_info->total_bytes + avail);
 
        return to_reclaim;
 }
@@ -856,11 +836,10 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
 {
        u64 global_rsv_size = fs_info->global_block_rsv.reserved;
        u64 ordered, delalloc;
-       u64 total = writable_total_bytes(fs_info, space_info);
        u64 thresh;
        u64 used;
 
-       thresh = mult_perc(total, 90);
+       thresh = mult_perc(space_info->total_bytes, 90);
 
        lockdep_assert_held(&space_info->lock);
 
@@ -923,8 +902,8 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
                                           BTRFS_RESERVE_FLUSH_ALL);
        used = space_info->bytes_used + space_info->bytes_reserved +
               space_info->bytes_readonly + global_rsv_size;
-       if (used < total)
-               thresh += total - used;
+       if (used < space_info->total_bytes)
+               thresh += space_info->total_bytes - used;
        thresh >>= space_info->clamp;
 
        used = space_info->bytes_pinned;
@@ -1651,7 +1630,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,
         * can_overcommit() to ensure we can overcommit to continue.
         */
        if (!pending_tickets &&
-           ((used + orig_bytes <= writable_total_bytes(fs_info, space_info)) ||
+           ((used + orig_bytes <= space_info->total_bytes) ||
             btrfs_can_overcommit(fs_info, space_info, orig_bytes, flush))) {
                btrfs_space_info_update_bytes_may_use(fs_info, space_info,
                                                      orig_bytes);
@@ -1665,8 +1644,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,
         */
        if (ret && unlikely(flush == BTRFS_RESERVE_FLUSH_EMERGENCY)) {
                used = btrfs_space_info_used(space_info, false);
-               if (used + orig_bytes <=
-                   writable_total_bytes(fs_info, space_info)) {
+               if (used + orig_bytes <= space_info->total_bytes) {
                        btrfs_space_info_update_bytes_may_use(fs_info, space_info,
                                                              orig_bytes);
                        ret = 0;
index fc99ea2..2033b71 100644 (file)
@@ -96,8 +96,6 @@ struct btrfs_space_info {
        u64 bytes_may_use;      /* number of bytes that may be used for
                                   delalloc/allocations */
        u64 bytes_readonly;     /* total bytes that are read only */
-       /* Total bytes in the space, but only accounts active block groups. */
-       u64 active_total_bytes;
        u64 bytes_zone_unusable;        /* total bytes that are unusable until
                                           resetting the device zone */
 
index 7823168..6d0124b 100644 (file)
@@ -6363,7 +6363,8 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        ASSERT(op != BTRFS_MAP_DISCARD);
 
        em = btrfs_get_chunk_map(fs_info, logical, *length);
-       ASSERT(!IS_ERR(em));
+       if (IS_ERR(em))
+               return PTR_ERR(em);
 
        map = em->map_lookup;
        data_stripes = nr_data_stripes(map);
index f95b2c9..45d0409 100644 (file)
@@ -524,8 +524,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
                }
                atomic_set(&zone_info->active_zones_left,
                           max_active_zones - nactive);
-               /* Overcommit does not work well with active zone tacking. */
-               set_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags);
+               set_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags);
        }
 
        /* Validate superblock log */
@@ -1581,9 +1580,19 @@ void btrfs_calc_zone_unusable(struct btrfs_block_group *cache)
                return;
 
        WARN_ON(cache->bytes_super != 0);
-       unusable = (cache->alloc_offset - cache->used) +
-                  (cache->length - cache->zone_capacity);
-       free = cache->zone_capacity - cache->alloc_offset;
+
+       /* Check for block groups never get activated */
+       if (test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &cache->fs_info->flags) &&
+           cache->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM) &&
+           !test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &cache->runtime_flags) &&
+           cache->alloc_offset == 0) {
+               unusable = cache->length;
+               free = 0;
+       } else {
+               unusable = (cache->alloc_offset - cache->used) +
+                          (cache->length - cache->zone_capacity);
+               free = cache->zone_capacity - cache->alloc_offset;
+       }
 
        /* We only need ->free_space in ALLOC_SEQ block groups */
        cache->cached = BTRFS_CACHE_FINISHED;
@@ -1902,7 +1911,11 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
 
        /* Successfully activated all the zones */
        set_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags);
-       space_info->active_total_bytes += block_group->length;
+       WARN_ON(block_group->alloc_offset != 0);
+       if (block_group->zone_unusable == block_group->length) {
+               block_group->zone_unusable = block_group->length - block_group->zone_capacity;
+               space_info->bytes_zone_unusable -= block_group->zone_capacity;
+       }
        spin_unlock(&block_group->lock);
        btrfs_try_granting_tickets(fs_info, space_info);
        spin_unlock(&space_info->lock);
@@ -2086,11 +2099,21 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
                if (!device->bdev)
                        continue;
 
-               if (!zinfo->max_active_zones ||
-                   atomic_read(&zinfo->active_zones_left)) {
+               if (!zinfo->max_active_zones) {
                        ret = true;
                        break;
                }
+
+               switch (flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+               case 0: /* single */
+                       ret = (atomic_read(&zinfo->active_zones_left) >= 1);
+                       break;
+               case BTRFS_BLOCK_GROUP_DUP:
+                       ret = (atomic_read(&zinfo->active_zones_left) >= 2);
+                       break;
+               }
+               if (ret)
+                       break;
        }
        mutex_unlock(&fs_info->chunk_mutex);
 
@@ -2256,7 +2279,7 @@ int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
                u64 avail;
 
                spin_lock(&block_group->lock);
-               if (block_group->reserved ||
+               if (block_group->reserved || block_group->alloc_offset == 0 ||
                    (block_group->flags & BTRFS_BLOCK_GROUP_SYSTEM)) {
                        spin_unlock(&block_group->lock);
                        continue;
@@ -2293,10 +2316,6 @@ int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
        if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
                return 0;
 
-       /* No more block groups to activate */
-       if (space_info->active_total_bytes == space_info->total_bytes)
-               return 0;
-
        for (;;) {
                int ret;
                bool need_finish = false;
index 75d5e06..bfc964b 100644 (file)
@@ -99,6 +99,23 @@ path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path)
        return dentry;
 }
 
+static const char *path_no_prefix(struct cifs_sb_info *cifs_sb,
+                                 const char *path)
+{
+       size_t len = 0;
+
+       if (!*path)
+               return path;
+
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
+           cifs_sb->prepath) {
+               len = strlen(cifs_sb->prepath) + 1;
+               if (unlikely(len > strlen(path)))
+                       return ERR_PTR(-EINVAL);
+       }
+       return path + len;
+}
+
 /*
  * Open the and cache a directory handle.
  * If error then *cfid is not initialized.
@@ -125,6 +142,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
        struct dentry *dentry = NULL;
        struct cached_fid *cfid;
        struct cached_fids *cfids;
+       const char *npath;
 
        if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache ||
            is_smb1_server(tcon->ses->server))
@@ -161,6 +179,20 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
        }
 
        /*
+        * Skip any prefix paths in @path as lookup_positive_unlocked() ends up
+        * calling ->lookup() which already adds those through
+        * build_path_from_dentry().  Also, do it earlier as we might reconnect
+        * below when trying to send compounded request and then potentially
+        * having a different prefix path (e.g. after DFS failover).
+        */
+       npath = path_no_prefix(cifs_sb, path);
+       if (IS_ERR(npath)) {
+               rc = PTR_ERR(npath);
+               kfree(utf16_path);
+               return rc;
+       }
+
+       /*
         * We do not hold the lock for the open because in case
         * SMB2_open needs to reconnect.
         * This is safe because no other thread will be able to get a ref
@@ -184,6 +216,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
@@ -251,10 +284,10 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
                                (char *)&cfid->file_all_info))
                cfid->file_all_info_is_valid = true;
 
-       if (!path[0])
+       if (!npath[0])
                dentry = dget(cifs_sb->root);
        else {
-               dentry = path_to_dentry(cifs_sb, path);
+               dentry = path_to_dentry(cifs_sb, npath);
                if (IS_ERR(dentry)) {
                        rc = -ENOENT;
                        goto oshr_free;
index 19a70a6..e9c8c08 100644 (file)
@@ -176,7 +176,7 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
 
        seq_puts(m, "# Version:1\n");
        seq_puts(m, "# Format:\n");
-       seq_puts(m, "# <tree id> <persistent fid> <flags> <count> <pid> <uid>");
+       seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
 #ifdef CONFIG_CIFS_DEBUG2
        seq_printf(m, " <filename> <mid>\n");
 #else
@@ -189,8 +189,9 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
                                spin_lock(&tcon->open_file_lock);
                                list_for_each_entry(cfile, &tcon->openFileList, tlist) {
                                        seq_printf(m,
-                                               "0x%x 0x%llx 0x%x %d %d %d %pd",
+                                               "0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd",
                                                tcon->tid,
+                                               ses->Suid,
                                                cfile->fid.persistent_fid,
                                                cfile->f_flags,
                                                cfile->count,
@@ -216,6 +217,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 {
        struct mid_q_entry *mid_entry;
        struct TCP_Server_Info *server;
+       struct TCP_Server_Info *chan_server;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
        struct cifs_server_iface *iface;
@@ -474,23 +476,35 @@ skip_rdma:
                                        seq_puts(m, "\t\t[CONNECTED]\n");
                        }
                        spin_unlock(&ses->iface_lock);
+
+                       seq_puts(m, "\n\n\tMIDs: ");
+                       spin_lock(&ses->chan_lock);
+                       for (j = 0; j < ses->chan_count; j++) {
+                               chan_server = ses->chans[j].server;
+                               if (!chan_server)
+                                       continue;
+
+                               if (list_empty(&chan_server->pending_mid_q))
+                                       continue;
+
+                               seq_printf(m, "\n\tServer ConnectionId: 0x%llx",
+                                          chan_server->conn_id);
+                               spin_lock(&chan_server->mid_lock);
+                               list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) {
+                                       seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu",
+                                                  mid_entry->mid_state,
+                                                  le16_to_cpu(mid_entry->command),
+                                                  mid_entry->pid,
+                                                  mid_entry->callback_data,
+                                                  mid_entry->mid);
+                               }
+                               spin_unlock(&chan_server->mid_lock);
+                       }
+                       spin_unlock(&ses->chan_lock);
+                       seq_puts(m, "\n--\n");
                }
                if (i == 0)
                        seq_printf(m, "\n\t\t[NONE]");
-
-               seq_puts(m, "\n\n\tMIDs: ");
-               spin_lock(&server->mid_lock);
-               list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
-                       seq_printf(m, "\n\tState: %d com: %d pid:"
-                                       " %d cbdata: %p mid %llu\n",
-                                       mid_entry->mid_state,
-                                       le16_to_cpu(mid_entry->command),
-                                       mid_entry->pid,
-                                       mid_entry->callback_data,
-                                       mid_entry->mid);
-               }
-               spin_unlock(&server->mid_lock);
-               seq_printf(m, "\n--\n");
        }
        if (c == 0)
                seq_printf(m, "\n\t[NONE]");
index cbcf210..ac9034f 100644 (file)
@@ -731,13 +731,16 @@ static void cifs_umount_begin(struct super_block *sb)
        spin_lock(&tcon->tc_lock);
        if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
                /* we have other mounts to same share or we have
-                  already tried to force umount this and woken up
+                  already tried to umount this and woken up
                   all waiting network requests, nothing to do */
                spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
                return;
-       } else if (tcon->tc_count == 1)
-               tcon->status = TID_EXITING;
+       }
+       /*
+        * can not set tcon->status to TID_EXITING yet since we don't know if umount -f will
+        * fail later (e.g. due to open files).  TID_EXITING will be set just before tdis req sent
+        */
        spin_unlock(&tcon->tc_lock);
        spin_unlock(&cifs_tcp_ses_lock);
 
index a43c783..38a697e 100644 (file)
@@ -86,13 +86,11 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 
        /*
         * only tree disconnect, open, and write, (and ulogoff which does not
-        * have tcon) are allowed as we start force umount
+        * have tcon) are allowed as we start umount
         */
        spin_lock(&tcon->tc_lock);
        if (tcon->status == TID_EXITING) {
-               if (smb_command != SMB_COM_WRITE_ANDX &&
-                   smb_command != SMB_COM_OPEN_ANDX &&
-                   smb_command != SMB_COM_TREE_DISCONNECT) {
+               if (smb_command != SMB_COM_TREE_DISCONNECT) {
                        spin_unlock(&tcon->tc_lock);
                        cifs_dbg(FYI, "can not send cmd %d while umounting\n",
                                 smb_command);
index 0eceddd..1cbb905 100644 (file)
@@ -212,31 +212,42 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
                        cifs_chan_update_iface(ses, server);
 
                spin_lock(&ses->chan_lock);
-               if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server))
-                       goto next_session;
+               if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) {
+                       spin_unlock(&ses->chan_lock);
+                       continue;
+               }
 
                if (mark_smb_session)
                        CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses);
                else
                        cifs_chan_set_need_reconnect(ses, server);
 
+               cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
+                        __func__, ses->chans_need_reconnect);
+
                /* If all channels need reconnect, then tcon needs reconnect */
-               if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses))
-                       goto next_session;
+               if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+                       spin_unlock(&ses->chan_lock);
+                       continue;
+               }
+               spin_unlock(&ses->chan_lock);
 
+               spin_lock(&ses->ses_lock);
                ses->ses_status = SES_NEED_RECON;
+               spin_unlock(&ses->ses_lock);
 
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
                        tcon->need_reconnect = true;
+                       spin_lock(&tcon->tc_lock);
                        tcon->status = TID_NEED_RECON;
+                       spin_unlock(&tcon->tc_lock);
                }
                if (ses->tcon_ipc) {
                        ses->tcon_ipc->need_reconnect = true;
+                       spin_lock(&ses->tcon_ipc->tc_lock);
                        ses->tcon_ipc->status = TID_NEED_RECON;
+                       spin_unlock(&ses->tcon_ipc->tc_lock);
                }
-
-next_session:
-               spin_unlock(&ses->chan_lock);
        }
        spin_unlock(&cifs_tcp_ses_lock);
 }
@@ -1721,7 +1732,7 @@ out_err:
        return ERR_PTR(rc);
 }
 
-/* this function must be called with ses_lock held */
+/* this function must be called with ses_lock and chan_lock held */
 static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 {
        if (ctx->sectype != Unspecified &&
@@ -1732,12 +1743,8 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
         * If an existing session is limited to less channels than
         * requested, it should not be reused
         */
-       spin_lock(&ses->chan_lock);
-       if (ses->chan_max < ctx->max_channels) {
-               spin_unlock(&ses->chan_lock);
+       if (ses->chan_max < ctx->max_channels)
                return 0;
-       }
-       spin_unlock(&ses->chan_lock);
 
        switch (ses->sectype) {
        case Kerberos:
@@ -1865,10 +1872,13 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
                        spin_unlock(&ses->ses_lock);
                        continue;
                }
+               spin_lock(&ses->chan_lock);
                if (!match_session(ses, ctx)) {
+                       spin_unlock(&ses->chan_lock);
                        spin_unlock(&ses->ses_lock);
                        continue;
                }
+               spin_unlock(&ses->chan_lock);
                spin_unlock(&ses->ses_lock);
 
                ++ses->ses_count;
@@ -2314,6 +2324,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        WARN_ON(tcon->tc_count < 0);
 
        list_del_init(&tcon->tcon_list);
+       tcon->status = TID_EXITING;
        spin_unlock(&tcon->tc_lock);
        spin_unlock(&cifs_tcp_ses_lock);
 
@@ -2693,6 +2704,7 @@ cifs_match_super(struct super_block *sb, void *data)
 
        spin_lock(&tcp_srv->srv_lock);
        spin_lock(&ses->ses_lock);
+       spin_lock(&ses->chan_lock);
        spin_lock(&tcon->tc_lock);
        if (!match_server(tcp_srv, ctx, dfs_super_cmp) ||
            !match_session(ses, ctx) ||
@@ -2705,6 +2717,7 @@ cifs_match_super(struct super_block *sb, void *data)
        rc = compare_mount_options(sb, mnt_data);
 out:
        spin_unlock(&tcon->tc_lock);
+       spin_unlock(&ses->chan_lock);
        spin_unlock(&ses->ses_lock);
        spin_unlock(&tcp_srv->srv_lock);
 
@@ -3652,11 +3665,19 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
 
        /* only send once per connect */
        spin_lock(&server->srv_lock);
-       if (!server->ops->need_neg(server) ||
+       if (server->tcpStatus != CifsGood &&
+           server->tcpStatus != CifsNew &&
            server->tcpStatus != CifsNeedNegotiate) {
                spin_unlock(&server->srv_lock);
+               return -EHOSTDOWN;
+       }
+
+       if (!server->ops->need_neg(server) &&
+           server->tcpStatus == CifsGood) {
+               spin_unlock(&server->srv_lock);
                return 0;
        }
+
        server->tcpStatus = CifsInNegotiate;
        spin_unlock(&server->srv_lock);
 
@@ -3690,23 +3711,28 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
        bool is_binding = false;
 
        spin_lock(&ses->ses_lock);
+       cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
+                __func__, ses->chans_need_reconnect);
+
        if (ses->ses_status != SES_GOOD &&
            ses->ses_status != SES_NEW &&
            ses->ses_status != SES_NEED_RECON) {
                spin_unlock(&ses->ses_lock);
-               return 0;
+               return -EHOSTDOWN;
        }
 
        /* only send once per connect */
        spin_lock(&ses->chan_lock);
-       if (CIFS_ALL_CHANS_GOOD(ses) ||
-           cifs_chan_in_reconnect(ses, server)) {
+       if (CIFS_ALL_CHANS_GOOD(ses)) {
+               if (ses->ses_status == SES_NEED_RECON)
+                       ses->ses_status = SES_GOOD;
                spin_unlock(&ses->chan_lock);
                spin_unlock(&ses->ses_lock);
                return 0;
        }
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
+
        cifs_chan_set_in_reconnect(ses, server);
+       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
        spin_unlock(&ses->chan_lock);
 
        if (!is_binding)
@@ -4036,9 +4062,13 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
-       if (tcon->ses->ses_status != SES_GOOD ||
-           (tcon->status != TID_NEW &&
-           tcon->status != TID_NEED_TCON)) {
+       if (tcon->status != TID_NEW &&
+           tcon->status != TID_NEED_TCON) {
+               spin_unlock(&tcon->tc_lock);
+               return -EHOSTDOWN;
+       }
+
+       if (tcon->status == TID_GOOD) {
                spin_unlock(&tcon->tc_lock);
                return 0;
        }
index c8bda52..3a11716 100644 (file)
@@ -502,9 +502,13 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
-       if (tcon->ses->ses_status != SES_GOOD ||
-           (tcon->status != TID_NEW &&
-           tcon->status != TID_NEED_TCON)) {
+       if (tcon->status != TID_NEW &&
+           tcon->status != TID_NEED_TCON) {
+               spin_unlock(&tcon->tc_lock);
+               return -EHOSTDOWN;
+       }
+
+       if (tcon->status == TID_GOOD) {
                spin_unlock(&tcon->tc_lock);
                return 0;
        }
index 1c59811..30cbdf8 100644 (file)
@@ -1191,7 +1191,7 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
        }
 
        spin_lock(&ipc->tc_lock);
-       if (ses->ses_status != SES_GOOD || ipc->status != TID_GOOD) {
+       if (ipc->status != TID_GOOD) {
                spin_unlock(&ipc->tc_lock);
                cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", __func__);
                goto out;
index 4d4a2d8..6831a99 100644 (file)
@@ -174,13 +174,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
        struct list_head *tmp1;
 
        /* only send once per connect */
-       spin_lock(&tcon->ses->ses_lock);
-       if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) {
-               spin_unlock(&tcon->ses->ses_lock);
+       spin_lock(&tcon->tc_lock);
+       if (tcon->status != TID_NEED_RECON) {
+               spin_unlock(&tcon->tc_lock);
                return;
        }
        tcon->status = TID_IN_FILES_INVALIDATE;
-       spin_unlock(&tcon->ses->ses_lock);
+       spin_unlock(&tcon->tc_lock);
 
        /* list all files open on tree connection and mark them invalid */
        spin_lock(&tcon->open_file_lock);
index 1b8d4e2..3de00e7 100644 (file)
@@ -286,5 +286,5 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
  * max deferred close timeout (jiffies) - 2^30
  */
 #define SMB3_MAX_DCLOSETIMEO (1 << 30)
-#define SMB3_DEF_DCLOSETIMEO (5 * HZ) /* Can increase later, other clients use larger */
+#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
 #endif
index 7d97c10..c66be49 100644 (file)
@@ -360,6 +360,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
                .cifs_sb = cifs_sb,
+               .path = path,
                .desired_access = GENERIC_READ,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
                .disposition = FILE_OPEN,
@@ -427,6 +428,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
                .cifs_sb = cifs_sb,
+               .path = path,
                .desired_access = GENERIC_WRITE,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
                .disposition = FILE_CREATE,
index 8dd3791..163a032 100644 (file)
@@ -107,6 +107,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 
        vars->oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = desired_access,
                .disposition = create_disposition,
                .create_options = cifs_create_options(cifs_sb, create_options),
index 6dfb865..a817582 100644 (file)
@@ -530,6 +530,14 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
        p = buf;
 
        spin_lock(&ses->iface_lock);
+       /* do not query too frequently, this time with lock held */
+       if (ses->iface_last_update &&
+           time_before(jiffies, ses->iface_last_update +
+                       (SMB_INTERFACE_POLL_INTERVAL * HZ))) {
+               spin_unlock(&ses->iface_lock);
+               return 0;
+       }
+
        /*
         * Go through iface_list and do kref_put to remove
         * any unused ifaces. ifaces in use will be removed
@@ -696,6 +704,12 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
        struct network_interface_info_ioctl_rsp *out_buf = NULL;
        struct cifs_ses *ses = tcon->ses;
 
+       /* do not query too frequently */
+       if (ses->iface_last_update &&
+           time_before(jiffies, ses->iface_last_update +
+                       (SMB_INTERFACE_POLL_INTERVAL * HZ)))
+               return 0;
+
        rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
                        FSCTL_QUERY_NETWORK_INTERFACE_INFO,
                        NULL /* no data input */, 0 /* no data input */,
@@ -703,7 +717,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
        if (rc == -EOPNOTSUPP) {
                cifs_dbg(FYI,
                         "server does not support query network interfaces\n");
-               goto out;
+               ret_data_len = 0;
        } else if (rc != 0) {
                cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
                goto out;
@@ -731,6 +745,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = "",
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -774,6 +789,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = "",
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -821,6 +837,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -1105,6 +1122,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = FILE_WRITE_EA,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2096,6 +2114,7 @@ smb3_notify(const unsigned int xid, struct file *pfile,
        tcon = cifs_sb_master_tcon(cifs_sb);
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2168,6 +2187,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2500,6 +2520,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = desired_access,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2634,6 +2655,7 @@ smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = "",
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2928,6 +2950,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, create_options),
@@ -3068,6 +3091,7 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT),
@@ -3208,6 +3232,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = READ_CONTROL,
                .disposition = FILE_OPEN,
                /*
index 0e53265..6bd2aa6 100644 (file)
@@ -144,7 +144,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
               struct TCP_Server_Info *server)
 {
        int rc = 0;
-       struct nls_table *nls_codepage;
+       struct nls_table *nls_codepage = NULL;
        struct cifs_ses *ses;
 
        /*
@@ -165,13 +165,9 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
        spin_lock(&tcon->tc_lock);
        if (tcon->status == TID_EXITING) {
                /*
-                * only tree disconnect, open, and write,
-                * (and ulogoff which does not have tcon)
-                * are allowed as we start force umount.
+                * only tree disconnect allowed when disconnecting ...
                 */
-               if ((smb2_command != SMB2_WRITE) &&
-                  (smb2_command != SMB2_CREATE) &&
-                  (smb2_command != SMB2_TREE_DISCONNECT)) {
+               if (smb2_command != SMB2_TREE_DISCONNECT) {
                        spin_unlock(&tcon->tc_lock);
                        cifs_dbg(FYI, "can not send cmd %d while umounting\n",
                                 smb2_command);
@@ -203,6 +199,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
        }
        spin_unlock(&server->srv_lock);
 
+again:
        rc = cifs_wait_for_server_reconnect(server, tcon->retry);
        if (rc)
                return rc;
@@ -219,8 +216,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
                 tcon->ses->chans_need_reconnect,
                 tcon->need_reconnect);
 
-       nls_codepage = load_nls_default();
-
+       mutex_lock(&ses->session_mutex);
        /*
         * Recheck after acquire mutex. If another thread is negotiating
         * and the server never sends an answer the socket will be closed
@@ -229,28 +225,38 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
        spin_lock(&server->srv_lock);
        if (server->tcpStatus == CifsNeedReconnect) {
                spin_unlock(&server->srv_lock);
+               mutex_unlock(&ses->session_mutex);
+
+               if (tcon->retry)
+                       goto again;
+
                rc = -EHOSTDOWN;
                goto out;
        }
        spin_unlock(&server->srv_lock);
 
+       nls_codepage = load_nls_default();
+
        /*
         * need to prevent multiple threads trying to simultaneously
         * reconnect the same SMB session
         */
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       if (!cifs_chan_needs_reconnect(ses, server)) {
+       if (!cifs_chan_needs_reconnect(ses, server) &&
+           ses->ses_status == SES_GOOD) {
                spin_unlock(&ses->chan_lock);
-
+               spin_unlock(&ses->ses_lock);
                /* this means that we only need to tree connect */
                if (tcon->need_reconnect)
                        goto skip_sess_setup;
 
+               mutex_unlock(&ses->session_mutex);
                goto out;
        }
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
-       mutex_lock(&ses->session_mutex);
        rc = cifs_negotiate_protocol(0, ses, server);
        if (!rc) {
                rc = cifs_setup_session(0, ses, server, nls_codepage);
@@ -266,10 +272,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
                mutex_unlock(&ses->session_mutex);
                goto out;
        }
-       mutex_unlock(&ses->session_mutex);
 
 skip_sess_setup:
-       mutex_lock(&ses->session_mutex);
        if (!tcon->need_reconnect) {
                mutex_unlock(&ses->session_mutex);
                goto out;
@@ -284,7 +288,7 @@ skip_sess_setup:
        cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
        if (rc) {
                /* If sess reconnected but tcon didn't, something strange ... */
-               pr_warn_once("reconnect tcon failed rc = %d\n", rc);
+               cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc);
                goto out;
        }
 
@@ -1256,9 +1260,9 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
        if (rc)
                return rc;
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        if (is_binding) {
                req->hdr.SessionId = cpu_to_le64(ses->Suid);
@@ -1416,9 +1420,9 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
                goto out_put_spnego_key;
        }
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        /* keep session key if binding */
        if (!is_binding) {
@@ -1542,9 +1546,9 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
 
        cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        /* keep existing ses id and flags if binding */
        if (!is_binding) {
@@ -1610,9 +1614,9 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
 
        rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        /* keep existing ses id and flags if binding */
        if (!is_binding) {
@@ -2705,7 +2709,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
        rqst.rq_nvec = n_iov;
 
        /* no need to inc num_remote_opens because we close it just below */
-       trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE,
+       trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE_NOT_FILE,
                                    FILE_WRITE_ATTRIBUTES);
        /* resource #4: response buffer */
        rc = cifs_send_recv(xid, ses, server,
@@ -2973,7 +2977,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        if (rc)
                goto creat_exit;
 
-       trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid,
+       trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path,
                oparms->create_options, oparms->desired_access);
 
        rc = cifs_send_recv(xid, ses, server,
index d827b75..790acf6 100644 (file)
@@ -81,6 +81,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
        struct cifs_ses *ses = NULL;
        int i;
        int rc = 0;
+       bool is_binding = false;
 
        spin_lock(&cifs_tcp_ses_lock);
 
@@ -97,9 +98,12 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
        goto out;
 
 found:
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       if (cifs_chan_needs_reconnect(ses, server) &&
-           !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+
+       is_binding = (cifs_chan_needs_reconnect(ses, server) &&
+                     ses->ses_status == SES_GOOD);
+       if (is_binding) {
                /*
                 * If we are in the process of binding a new channel
                 * to an existing session, use the master connection
@@ -107,6 +111,7 @@ found:
                 */
                memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
                spin_unlock(&ses->chan_lock);
+               spin_unlock(&ses->ses_lock);
                goto out;
        }
 
@@ -119,10 +124,12 @@ found:
                if (chan->server == server) {
                        memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
                        spin_unlock(&ses->chan_lock);
+                       spin_unlock(&ses->ses_lock);
                        goto out;
                }
        }
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
        cifs_dbg(VFS,
                 "%s: Could not find channel signing key for session 0x%llx\n",
@@ -392,11 +399,15 @@ generate_smb3signingkey(struct cifs_ses *ses,
        bool is_binding = false;
        int chan_index = 0;
 
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
+       is_binding = (cifs_chan_needs_reconnect(ses, server) &&
+                     ses->ses_status == SES_GOOD);
+
        chan_index = cifs_ses_get_chan_index(ses, server);
        /* TODO: introduce ref counting for channels when the can be freed */
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
        /*
         * All channels use the same encryption/decryption keys but
index 110070b..d3053bd 100644 (file)
@@ -701,13 +701,15 @@ DECLARE_EVENT_CLASS(smb3_open_enter_class,
        TP_PROTO(unsigned int xid,
                __u32   tid,
                __u64   sesid,
+               const char *full_path,
                int     create_options,
                int     desired_access),
-       TP_ARGS(xid, tid, sesid, create_options, desired_access),
+       TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access),
        TP_STRUCT__entry(
                __field(unsigned int, xid)
                __field(__u32, tid)
                __field(__u64, sesid)
+               __string(path, full_path)
                __field(int, create_options)
                __field(int, desired_access)
        ),
@@ -715,11 +717,12 @@ DECLARE_EVENT_CLASS(smb3_open_enter_class,
                __entry->xid = xid;
                __entry->tid = tid;
                __entry->sesid = sesid;
+               __assign_str(path, full_path);
                __entry->create_options = create_options;
                __entry->desired_access = desired_access;
        ),
-       TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x",
-               __entry->xid, __entry->sesid, __entry->tid,
+       TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s cr_opts=0x%x des_access=0x%x",
+               __entry->xid, __entry->sesid, __entry->tid, __get_str(path),
                __entry->create_options, __entry->desired_access)
 )
 
@@ -728,9 +731,10 @@ DEFINE_EVENT(smb3_open_enter_class, smb3_##name,  \
        TP_PROTO(unsigned int xid,              \
                __u32   tid,                    \
                __u64   sesid,                  \
+               const char *full_path,          \
                int     create_options,         \
                int     desired_access),        \
-       TP_ARGS(xid, tid, sesid, create_options, desired_access))
+       TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access))
 
 DEFINE_SMB3_OPEN_ENTER_EVENT(open_enter);
 DEFINE_SMB3_OPEN_ENTER_EVENT(posix_mkdir_enter);
index 78086f8..13d336a 100644 (file)
@@ -92,6 +92,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
         * destroying any subkeys embedded in it.
         */
 
+       if (WARN_ON(!sb->s_master_keys))
+               return;
        spin_lock(&sb->s_master_keys->lock);
        hlist_del_rcu(&mk->mk_node);
        spin_unlock(&sb->s_master_keys->lock);
@@ -207,10 +209,11 @@ static int allocate_filesystem_keyring(struct super_block *sb)
  * Release all encryption keys that have been added to the filesystem, along
  * with the keyring that contains them.
  *
- * This is called at unmount time.  The filesystem's underlying block device(s)
- * are still available at this time; this is important because after user file
- * accesses have been allowed, this function may need to evict keys from the
- * keyslots of an inline crypto engine, which requires the block device(s).
+ * This is called at unmount time, after all potentially-encrypted inodes have
+ * been evicted.  The filesystem's underlying block device(s) are still
+ * available at this time; this is important because after user file accesses
+ * have been allowed, this function may need to evict keys from the keyslots of
+ * an inline crypto engine, which requires the block device(s).
  */
 void fscrypt_destroy_keyring(struct super_block *sb)
 {
@@ -227,12 +230,12 @@ void fscrypt_destroy_keyring(struct super_block *sb)
 
                hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
                        /*
-                        * Since all inodes were already evicted, every key
-                        * remaining in the keyring should have an empty inode
-                        * list, and should only still be in the keyring due to
-                        * the single active ref associated with ->mk_secret.
-                        * There should be no structural refs beyond the one
-                        * associated with the active ref.
+                        * Since all potentially-encrypted inodes were already
+                        * evicted, every key remaining in the keyring should
+                        * have an empty inode list, and should only still be in
+                        * the keyring due to the single active ref associated
+                        * with ->mk_secret.  There should be no structural refs
+                        * beyond the one associated with the active ref.
                         */
                        WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
                        WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
index 6fe9ca2..2e215e8 100644 (file)
@@ -83,8 +83,26 @@ static int gfs2_dhash(const struct dentry *dentry, struct qstr *str)
        return 0;
 }
 
+static int gfs2_dentry_delete(const struct dentry *dentry)
+{
+       struct gfs2_inode *ginode;
+
+       if (d_really_is_negative(dentry))
+               return 0;
+
+       ginode = GFS2_I(d_inode(dentry));
+       if (!gfs2_holder_initialized(&ginode->i_iopen_gh))
+               return 0;
+
+       if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags))
+               return 1;
+
+       return 0;
+}
+
 const struct dentry_operations gfs2_dops = {
        .d_revalidate = gfs2_drevalidate,
        .d_hash = gfs2_dhash,
+       .d_delete = gfs2_dentry_delete,
 };
 
index 6e61b5b..cead696 100644 (file)
@@ -727,8 +727,9 @@ static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                goto smb3signkey_ret;
        }
 
-       if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
-           conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+       if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
+           (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
+            conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
                rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
        else
                rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
index 5b10b03..115a67d 100644 (file)
@@ -298,7 +298,7 @@ int ksmbd_conn_handler_loop(void *p)
                kvfree(conn->request_buf);
                conn->request_buf = NULL;
 
-               size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
+               size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
                if (size != sizeof(hdr_buf))
                        break;
 
@@ -319,13 +319,10 @@ int ksmbd_conn_handler_loop(void *p)
                }
 
                /*
-                * Check if pdu size is valid (min : smb header size,
-                * max : 0x00FFFFFF).
+                * Check maximum pdu size(0x00FFFFFF).
                 */
-               if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
-                   pdu_size > MAX_STREAM_PROT_LEN) {
+               if (pdu_size > MAX_STREAM_PROT_LEN)
                        break;
-               }
 
                /* 4 for rfc1002 length field */
                size = pdu_size + 4;
@@ -344,7 +341,7 @@ int ksmbd_conn_handler_loop(void *p)
                 * We already read 4 bytes to find out PDU size, now
                 * read in PDU
                 */
-               size = t->ops->read(t, conn->request_buf + 4, pdu_size);
+               size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
                if (size < 0) {
                        pr_err("sock_read failed: %d\n", size);
                        break;
index 3643354..0e3a848 100644 (file)
@@ -114,7 +114,8 @@ struct ksmbd_transport_ops {
        int (*prepare)(struct ksmbd_transport *t);
        void (*disconnect)(struct ksmbd_transport *t);
        void (*shutdown)(struct ksmbd_transport *t);
-       int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
+       int (*read)(struct ksmbd_transport *t, char *buf,
+                   unsigned int size, int max_retries);
        int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
                      int size, bool need_invalidate_rkey,
                      unsigned int remote_key);
index 0685c1c..97c9d1b 100644 (file)
@@ -2977,8 +2977,11 @@ int smb2_open(struct ksmbd_work *work)
                                                        sizeof(struct smb_acl) +
                                                        sizeof(struct smb_ace) * ace_num * 2,
                                                        GFP_KERNEL);
-                                       if (!pntsd)
+                                       if (!pntsd) {
+                                               posix_acl_release(fattr.cf_acls);
+                                               posix_acl_release(fattr.cf_dacls);
                                                goto err_out;
+                                       }
 
                                        rc = build_sec_desc(idmap,
                                                            pntsd, NULL, 0,
@@ -4934,6 +4937,10 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
 
                info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
 
+               if (test_share_config_flag(work->tcon->share_conf,
+                   KSMBD_SHARE_FLAG_STREAMS))
+                       info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS);
+
                info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
                len = smbConvertToUTF16((__le16 *)info->FileSystemName,
                                        "NTFS", PATH_MAX, conn->local_nls, 0);
@@ -7444,13 +7451,16 @@ static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
        if (in_count == 0)
                return -EINVAL;
 
+       start = le64_to_cpu(qar_req->file_offset);
+       length = le64_to_cpu(qar_req->length);
+
+       if (start < 0 || length < 0)
+               return -EINVAL;
+
        fp = ksmbd_lookup_fd_fast(work, id);
        if (!fp)
                return -ENOENT;
 
-       start = le64_to_cpu(qar_req->file_offset);
-       length = le64_to_cpu(qar_req->length);
-
        ret = ksmbd_vfs_fqar_lseek(fp, start, length,
                                   qar_rsp, in_count, out_count);
        if (ret && ret != -E2BIG)
@@ -7751,7 +7761,7 @@ int smb2_ioctl(struct ksmbd_work *work)
 
                off = le64_to_cpu(zero_data->FileOffset);
                bfz = le64_to_cpu(zero_data->BeyondFinalZero);
-               if (off > bfz) {
+               if (off < 0 || bfz < 0 || off > bfz) {
                        ret = -EINVAL;
                        goto out;
                }
index fa2b54d..9c1ce6d 100644 (file)
@@ -434,7 +434,7 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
 
 static int __smb2_negotiate(struct ksmbd_conn *conn)
 {
-       return (conn->dialect >= SMB21_PROT_ID &&
+       return (conn->dialect >= SMB20_PROT_ID &&
                conn->dialect <= SMB311_PROT_ID);
 }
 
@@ -442,9 +442,26 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
 {
        struct smb_negotiate_rsp *neg_rsp = work->response_buf;
 
-       ksmbd_debug(SMB, "Unsupported SMB protocol\n");
-       neg_rsp->hdr.Status.CifsError = STATUS_INVALID_LOGON_TYPE;
-       return -EINVAL;
+       ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
+
+       /*
+        * Remove 4 byte direct TCP header, add 2 byte bcc and
+        * 2 byte DialectIndex.
+        */
+       *(__be32 *)work->response_buf =
+               cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2 + 2);
+       neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
+
+       neg_rsp->hdr.Command = SMB_COM_NEGOTIATE;
+       *(__le32 *)neg_rsp->hdr.Protocol = SMB1_PROTO_NUMBER;
+       neg_rsp->hdr.Flags = SMBFLG_RESPONSE;
+       neg_rsp->hdr.Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
+               SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
+
+       neg_rsp->hdr.WordCount = 1;
+       neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
+       neg_rsp->ByteCount = 0;
+       return 0;
 }
 
 int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
@@ -465,7 +482,7 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
                }
        }
 
-       if (command == SMB2_NEGOTIATE_HE && __smb2_negotiate(conn)) {
+       if (command == SMB2_NEGOTIATE_HE) {
                ret = smb2_handle_negotiate(work);
                init_smb2_neg_rsp(work);
                return ret;
index e663ab9..d30ce4c 100644 (file)
 
 #define SMB1_PROTO_NUMBER              cpu_to_le32(0x424d53ff)
 #define SMB_COM_NEGOTIATE              0x72
-
 #define SMB1_CLIENT_GUID_SIZE          (16)
+
+#define SMBFLG_RESPONSE 0x80   /* this PDU is a response from server */
+
+#define SMBFLG2_IS_LONG_NAME   cpu_to_le16(0x40)
+#define SMBFLG2_EXT_SEC                cpu_to_le16(0x800)
+#define SMBFLG2_ERR_STATUS     cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE                cpu_to_le16(0x8000)
+
 struct smb_hdr {
        __be32 smb_buf_length;
        __u8 Protocol[4];
@@ -199,28 +206,7 @@ struct smb_negotiate_req {
 struct smb_negotiate_rsp {
        struct smb_hdr hdr;     /* wct = 17 */
        __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
-       __u8 SecurityMode;
-       __le16 MaxMpxCount;
-       __le16 MaxNumberVcs;
-       __le32 MaxBufferSize;
-       __le32 MaxRawSize;
-       __le32 SessionKey;
-       __le32 Capabilities;    /* see below */
-       __le32 SystemTimeLow;
-       __le32 SystemTimeHigh;
-       __le16 ServerTimeZone;
-       __u8 EncryptionKeyLength;
        __le16 ByteCount;
-       union {
-               unsigned char EncryptionKey[8]; /* cap extended security off */
-               /* followed by Domain name - if extended security is off */
-               /* followed by 16 bytes of server GUID */
-               /* then security blob if cap_extended_security negotiated */
-               struct {
-                       unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
-                       unsigned char SecurityBlob[1];
-               } __packed extended_response;
-       } __packed u;
 } __packed;
 
 struct filesystem_attribute_info {
index 096eda9..c06efc0 100644 (file)
@@ -670,7 +670,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
 }
 
 static int smb_direct_read(struct ksmbd_transport *t, char *buf,
-                          unsigned int size)
+                          unsigned int size, int unused)
 {
        struct smb_direct_recvmsg *recvmsg;
        struct smb_direct_data_transfer *data_transfer;
index 603893f..20e85e2 100644 (file)
@@ -291,16 +291,18 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
 
 /**
  * ksmbd_tcp_readv() - read data from socket in given iovec
- * @t:         TCP transport instance
- * @iov_orig:  base IO vector
- * @nr_segs:   number of segments in base iov
- * @to_read:   number of bytes to read from socket
+ * @t:                 TCP transport instance
+ * @iov_orig:          base IO vector
+ * @nr_segs:           number of segments in base iov
+ * @to_read:           number of bytes to read from socket
+ * @max_retries:       maximum retry count
  *
  * Return:     on success return number of bytes read from socket,
  *             otherwise return error number
  */
 static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
-                          unsigned int nr_segs, unsigned int to_read)
+                          unsigned int nr_segs, unsigned int to_read,
+                          int max_retries)
 {
        int length = 0;
        int total_read;
@@ -308,7 +310,6 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
        struct msghdr ksmbd_msg;
        struct kvec *iov;
        struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
-       int max_retry = 2;
 
        iov = get_conn_iovec(t, nr_segs);
        if (!iov)
@@ -335,14 +336,23 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
                } else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
                        total_read = -EAGAIN;
                        break;
-               } else if ((length == -ERESTARTSYS || length == -EAGAIN) &&
-                          max_retry) {
+               } else if (length == -ERESTARTSYS || length == -EAGAIN) {
+                       /*
+                        * If max_retries is negative, Allow unlimited
+                        * retries to keep connection with inactive sessions.
+                        */
+                       if (max_retries == 0) {
+                               total_read = length;
+                               break;
+                       } else if (max_retries > 0) {
+                               max_retries--;
+                       }
+
                        usleep_range(1000, 2000);
                        length = 0;
-                       max_retry--;
                        continue;
                } else if (length <= 0) {
-                       total_read = -EAGAIN;
+                       total_read = length;
                        break;
                }
        }
@@ -358,14 +368,15 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
  * Return:     on success return number of bytes read from socket,
  *             otherwise return error number
  */
-static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf, unsigned int to_read)
+static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
+                         unsigned int to_read, int max_retries)
 {
        struct kvec iov;
 
        iov.iov_base = buf;
        iov.iov_len = to_read;
 
-       return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read);
+       return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
 }
 
 static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
index 7df6324..8161667 100644 (file)
@@ -261,7 +261,6 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
        u32 exclusive;
        int error;
        __be32 *p;
-       s32 end;
 
        memset(lock, 0, sizeof(*lock));
        locks_init_lock(fl);
@@ -285,13 +284,7 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
        fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
        p = xdr_decode_hyper(p, &l_offset);
        xdr_decode_hyper(p, &l_len);
-       end = l_offset + l_len - 1;
-
-       fl->fl_start = (loff_t)l_offset;
-       if (l_len == 0 || end < 0)
-               fl->fl_end = OFFSET_MAX;
-       else
-               fl->fl_end = (loff_t)end;
+       nlm4svc_set_file_lock_range(fl, l_offset, l_len);
        error = 0;
 out:
        return error;
index 712fdfe..5fcbf30 100644 (file)
@@ -33,6 +33,17 @@ loff_t_to_s64(loff_t offset)
        return res;
 }
 
+void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len)
+{
+       s64 end = off + len - 1;
+
+       fl->fl_start = off;
+       if (len == 0 || end < 0)
+               fl->fl_end = OFFSET_MAX;
+       else
+               fl->fl_end = end;
+}
+
 /*
  * NLM file handles are defined by specification to be a variable-length
  * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -80,7 +91,7 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
        locks_init_lock(fl);
        fl->fl_flags = FL_POSIX;
        fl->fl_type  = F_RDLCK;
-
+       nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
        return true;
 }
 
index 14a7222..450d6c3 100644 (file)
@@ -75,7 +75,7 @@ config NFS_V3_ACL
 config NFS_V4
        tristate "NFS client support for NFS version 4"
        depends on NFS_FS
-       select SUNRPC_GSS
+       select RPCSEC_GSS_KRB5
        select KEYS
        help
          This option enables support for version 4 of the NFS protocol
index a41c3ee..6fbcbb8 100644 (file)
@@ -3089,7 +3089,6 @@ static void nfs_access_add_rbtree(struct inode *inode,
                else
                        goto found;
        }
-       set->timestamp = ktime_get_ns();
        rb_link_node(&set->rb_node, parent, p);
        rb_insert_color(&set->rb_node, root_node);
        list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
@@ -3114,6 +3113,7 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
        cache->fsgid = cred->fsgid;
        cache->group_info = get_group_info(cred->group_info);
        cache->mask = set->mask;
+       cache->timestamp = ktime_get_ns();
 
        /* The above field assignments must be visible
         * before this item appears on the lru.  We cannot easily
index c380cff..e909885 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
@@ -337,6 +338,7 @@ int nfs_read_folio(struct file *file, struct folio *folio)
 
        trace_nfs_aop_readpage(inode, folio);
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
+       task_io_account_read(folio_size(folio));
 
        /*
         * Try to flush any pending writes to the file..
@@ -393,6 +395,7 @@ void nfs_readahead(struct readahead_control *ractl)
 
        trace_nfs_aop_readahead(inode, readahead_pos(ractl), nr_pages);
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
+       task_io_account_read(readahead_length(ractl));
 
        ret = -ESTALE;
        if (NFS_STALE(inode))
index 7c441f2..43b88ea 100644 (file)
@@ -73,7 +73,7 @@ config NFSD_V4
        bool "NFS server support for NFS version 4"
        depends on NFSD && PROC_FS
        select FS_POSIX_ACL
-       select SUNRPC_GSS
+       select RPCSEC_GSS_KRB5
        select CRYPTO
        select CRYPTO_MD5
        select CRYPTO_SHA256
index 502e1b7..5783209 100644 (file)
@@ -941,8 +941,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
        struct page *last_page;
 
        last_page = page + (offset + sd->len - 1) / PAGE_SIZE;
-       for (page += offset / PAGE_SIZE; page <= last_page; page++)
+       for (page += offset / PAGE_SIZE; page <= last_page; page++) {
+               /*
+                * Skip page replacement when extending the contents
+                * of the current page.
+                */
+               if (page == *(rqstp->rq_next_page - 1))
+                       continue;
                svc_rqst_replace_page(rqstp, page);
+       }
        if (rqstp->rq_res.page_len == 0)        // first call
                rqstp->rq_res.page_base = offset % PAGE_SIZE;
        rqstp->rq_res.page_len += sd->len;
index 5ccc638..1dfbc0c 100644 (file)
@@ -71,7 +71,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
        if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
                return -EINVAL;
 
-       buf = (void *)__get_free_pages(GFP_NOFS, 0);
+       buf = (void *)get_zeroed_page(GFP_NOFS);
        if (unlikely(!buf))
                return -ENOMEM;
        maxmembs = PAGE_SIZE / argv->v_size;
index 84332d5..04bc62a 100644 (file)
@@ -475,13 +475,22 @@ void generic_shutdown_super(struct super_block *sb)
 
                cgroup_writeback_umount();
 
-               /* evict all inodes with zero refcount */
+               /* Evict all inodes with zero refcount. */
                evict_inodes(sb);
-               /* only nonzero refcount inodes can have marks */
+
+               /*
+                * Clean up and evict any inodes that still have references due
+                * to fsnotify or the security policy.
+                */
                fsnotify_sb_delete(sb);
-               fscrypt_destroy_keyring(sb);
                security_sb_delete(sb);
 
+               /*
+                * Now that all potentially-encrypted inodes have been evicted,
+                * the fscrypt keyring can be destroyed.
+                */
+               fscrypt_destroy_keyring(sb);
+
                if (sb->s_dio_done_wq) {
                        destroy_workqueue(sb->s_dio_done_wq);
                        sb->s_dio_done_wq = NULL;
index e13db65..7a0e3a8 100644 (file)
@@ -8,7 +8,6 @@
 #include "fsverity_private.h"
 
 #include <linux/mount.h>
-#include <linux/pagemap.h>
 #include <linux/sched/signal.h>
 #include <linux/uaccess.h>
 
@@ -367,25 +366,27 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
                goto out_drop_write;
 
        err = enable_verity(filp, &arg);
-       if (err)
-               goto out_allow_write_access;
 
        /*
-        * Some pages of the file may have been evicted from pagecache after
-        * being used in the Merkle tree construction, then read into pagecache
-        * again by another process reading from the file concurrently.  Since
-        * these pages didn't undergo verification against the file digest which
-        * fs-verity now claims to be enforcing, we have to wipe the pagecache
-        * to ensure that all future reads are verified.
+        * We no longer drop the inode's pagecache after enabling verity.  This
+        * used to be done to try to avoid a race condition where pages could be
+        * evicted after being used in the Merkle tree construction, then
+        * re-instantiated by a concurrent read.  Such pages are unverified, and
+        * the backing storage could have filled them with different content, so
+        * they shouldn't be used to fulfill reads once verity is enabled.
+        *
+        * But, dropping the pagecache has a big performance impact, and it
+        * doesn't fully solve the race condition anyway.  So for those reasons,
+        * and also because this race condition isn't very important relatively
+        * speaking (especially for small-ish files, where the chance of a page
+        * being used, evicted, *and* re-instantiated all while enabling verity
+        * is quite small), we no longer drop the inode's pagecache.
         */
-       filemap_write_and_wait(inode->i_mapping);
-       invalidate_inode_pages2(inode->i_mapping);
 
        /*
         * allow_write_access() is needed to pair with deny_write_access().
         * Regardless, the filesystem won't allow writing to verity files.
         */
-out_allow_write_access:
        allow_write_access(filp);
 out_drop_write:
        mnt_drop_write_file(filp);
index f50e3b5..e250822 100644 (file)
@@ -387,15 +387,15 @@ EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work);
 int __init fsverity_init_workqueue(void)
 {
        /*
-        * Use an unbound workqueue to allow bios to be verified in parallel
-        * even when they happen to complete on the same CPU.  This sacrifices
-        * locality, but it's worthwhile since hashing is CPU-intensive.
+        * Use a high-priority workqueue to prioritize verification work, which
+        * blocks reads from completing, over regular application tasks.
         *
-        * Also use a high-priority workqueue to prioritize verification work,
-        * which blocks reads from completing, over regular application tasks.
+        * For performance reasons, don't use an unbound workqueue.  Using an
+        * unbound workqueue for crypto operations causes excessive scheduler
+        * latency on ARM64.
         */
        fsverity_read_workqueue = alloc_workqueue("fsverity_read_queue",
-                                                 WQ_UNBOUND | WQ_HIGHPRI,
+                                                 WQ_HIGHPRI,
                                                  num_online_cpus());
        if (!fsverity_read_workqueue)
                return -ENOMEM;
index 03135a1..92d88dc 100644 (file)
@@ -63,6 +63,7 @@ xfs-y                         += xfs_aops.o \
                                   xfs_bmap_util.o \
                                   xfs_bio_io.o \
                                   xfs_buf.o \
+                                  xfs_dahash_test.o \
                                   xfs_dir2_readdir.o \
                                   xfs_discard.o \
                                   xfs_error.o \
index 6a03717..203f16c 100644 (file)
@@ -3045,6 +3045,8 @@ xfs_alloc_read_agf(
                pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
                if (xfs_agfl_needs_reset(pag->pag_mount, agf))
                        set_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
+               else
+                       clear_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
 
                /*
                 * Update the in-core allocbt counter. Filter out the rmapbt
@@ -3255,6 +3257,8 @@ xfs_alloc_vextent_finish(
        XFS_STATS_INC(mp, xs_allocx);
        XFS_STATS_ADD(mp, xs_allocb, args->len);
 
+       trace_xfs_alloc_vextent_finish(args);
+
 out_drop_perag:
        if (drop_perag && args->pag) {
                xfs_perag_rele(args->pag);
@@ -3279,8 +3283,14 @@ xfs_alloc_vextent_this_ag(
        xfs_agnumber_t          minimum_agno;
        int                     error;
 
+       ASSERT(args->pag != NULL);
+       ASSERT(args->pag->pag_agno == agno);
+
        args->agno = agno;
        args->agbno = 0;
+
+       trace_xfs_alloc_vextent_this_ag(args);
+
        error = xfs_alloc_vextent_check_args(args, XFS_AGB_TO_FSB(mp, agno, 0),
                        &minimum_agno);
        if (error) {
@@ -3323,11 +3333,14 @@ xfs_alloc_vextent_iterate_ags(
        uint32_t                flags)
 {
        struct xfs_mount        *mp = args->mp;
+       xfs_agnumber_t          restart_agno = minimum_agno;
        xfs_agnumber_t          agno;
        int                     error = 0;
 
+       if (flags & XFS_ALLOC_FLAG_TRYLOCK)
+               restart_agno = 0;
 restart:
-       for_each_perag_wrap_range(mp, start_agno, minimum_agno,
+       for_each_perag_wrap_range(mp, start_agno, restart_agno,
                        mp->m_sb.sb_agcount, agno, args->pag) {
                args->agno = agno;
                error = xfs_alloc_vextent_prepare_ag(args);
@@ -3366,6 +3379,7 @@ restart:
         */
        if (flags) {
                flags = 0;
+               restart_agno = minimum_agno;
                goto restart;
        }
 
@@ -3394,8 +3408,13 @@ xfs_alloc_vextent_start_ag(
        bool                    bump_rotor = false;
        int                     error;
 
+       ASSERT(args->pag == NULL);
+
        args->agno = NULLAGNUMBER;
        args->agbno = NULLAGBLOCK;
+
+       trace_xfs_alloc_vextent_start_ag(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
@@ -3442,8 +3461,13 @@ xfs_alloc_vextent_first_ag(
        xfs_agnumber_t          start_agno;
        int                     error;
 
+       ASSERT(args->pag == NULL);
+
        args->agno = NULLAGNUMBER;
        args->agbno = NULLAGBLOCK;
+
+       trace_xfs_alloc_vextent_first_ag(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
@@ -3470,8 +3494,14 @@ xfs_alloc_vextent_exact_bno(
        xfs_agnumber_t          minimum_agno;
        int                     error;
 
+       ASSERT(args->pag != NULL);
+       ASSERT(args->pag->pag_agno == XFS_FSB_TO_AGNO(mp, target));
+
        args->agno = XFS_FSB_TO_AGNO(mp, target);
        args->agbno = XFS_FSB_TO_AGBNO(mp, target);
+
+       trace_xfs_alloc_vextent_exact_bno(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
@@ -3502,8 +3532,14 @@ xfs_alloc_vextent_near_bno(
        bool                    needs_perag = args->pag == NULL;
        int                     error;
 
+       if (!needs_perag)
+               ASSERT(args->pag->pag_agno == XFS_FSB_TO_AGNO(mp, target));
+
        args->agno = XFS_FSB_TO_AGNO(mp, target);
        args->agbno = XFS_FSB_TO_AGBNO(mp, target);
+
+       trace_xfs_alloc_vextent_near_bno(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
diff --git a/fs/xfs/xfs_dahash_test.c b/fs/xfs/xfs_dahash_test.c
new file mode 100644 (file)
index 0000000..230651a
--- /dev/null
@@ -0,0 +1,662 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_dahash_test.h"
+
+/* 4096 random bytes */
+static uint8_t __initdata __attribute__((__aligned__(8))) test_buf[] =
+{
+       0x5b, 0x85, 0x21, 0xcb, 0x09, 0x68, 0x7d, 0x30,
+       0xc7, 0x69, 0xd7, 0x30, 0x92, 0xde, 0x59, 0xe4,
+       0xc9, 0x6e, 0x8b, 0xdb, 0x98, 0x6b, 0xaa, 0x60,
+       0xa8, 0xb5, 0xbc, 0x6c, 0xa9, 0xb1, 0x5b, 0x2c,
+       0xea, 0xb4, 0x92, 0x6a, 0x3f, 0x79, 0x91, 0xe4,
+       0xe9, 0x70, 0x51, 0x8c, 0x7f, 0x95, 0x6f, 0x1a,
+       0x56, 0xa1, 0x5c, 0x27, 0x03, 0x67, 0x9f, 0x3a,
+       0xe2, 0x31, 0x11, 0x29, 0x6b, 0x98, 0xfc, 0xc4,
+       0x53, 0x24, 0xc5, 0x8b, 0xce, 0x47, 0xb2, 0xb9,
+       0x32, 0xcb, 0xc1, 0xd0, 0x03, 0x57, 0x4e, 0xd4,
+       0xe9, 0x3c, 0xa1, 0x63, 0xcf, 0x12, 0x0e, 0xca,
+       0xe1, 0x13, 0xd1, 0x93, 0xa6, 0x88, 0x5c, 0x61,
+       0x5b, 0xbb, 0xf0, 0x19, 0x46, 0xb4, 0xcf, 0x9e,
+       0xb6, 0x6b, 0x4c, 0x3a, 0xcf, 0x60, 0xf9, 0x7a,
+       0x8d, 0x07, 0x63, 0xdb, 0x40, 0xe9, 0x0b, 0x6f,
+       0xad, 0x97, 0xf1, 0xed, 0xd0, 0x1e, 0x26, 0xfd,
+       0xbf, 0xb7, 0xc8, 0x04, 0x94, 0xf8, 0x8b, 0x8c,
+       0xf1, 0xab, 0x7a, 0xd4, 0xdd, 0xf3, 0xe8, 0x88,
+       0xc3, 0xed, 0x17, 0x8a, 0x9b, 0x40, 0x0d, 0x53,
+       0x62, 0x12, 0x03, 0x5f, 0x1b, 0x35, 0x32, 0x1f,
+       0xb4, 0x7b, 0x93, 0x78, 0x0d, 0xdb, 0xce, 0xa4,
+       0xc0, 0x47, 0xd5, 0xbf, 0x68, 0xe8, 0x5d, 0x74,
+       0x8f, 0x8e, 0x75, 0x1c, 0xb2, 0x4f, 0x9a, 0x60,
+       0xd1, 0xbe, 0x10, 0xf4, 0x5c, 0xa1, 0x53, 0x09,
+       0xa5, 0xe0, 0x09, 0x54, 0x85, 0x5c, 0xdc, 0x07,
+       0xe7, 0x21, 0x69, 0x7b, 0x8a, 0xfd, 0x90, 0xf1,
+       0x22, 0xd0, 0xb4, 0x36, 0x28, 0xe6, 0xb8, 0x0f,
+       0x39, 0xde, 0xc8, 0xf3, 0x86, 0x60, 0x34, 0xd2,
+       0x5e, 0xdf, 0xfd, 0xcf, 0x0f, 0xa9, 0x65, 0xf0,
+       0xd5, 0x4d, 0x96, 0x40, 0xe3, 0xdf, 0x3f, 0x95,
+       0x5a, 0x39, 0x19, 0x93, 0xf4, 0x75, 0xce, 0x22,
+       0x00, 0x1c, 0x93, 0xe2, 0x03, 0x66, 0xf4, 0x93,
+       0x73, 0x86, 0x81, 0x8e, 0x29, 0x44, 0x48, 0x86,
+       0x61, 0x7c, 0x48, 0xa3, 0x43, 0xd2, 0x9c, 0x8d,
+       0xd4, 0x95, 0xdd, 0xe1, 0x22, 0x89, 0x3a, 0x40,
+       0x4c, 0x1b, 0x8a, 0x04, 0xa8, 0x09, 0x69, 0x8b,
+       0xea, 0xc6, 0x55, 0x8e, 0x57, 0xe6, 0x64, 0x35,
+       0xf0, 0xc7, 0x16, 0x9f, 0x5d, 0x5e, 0x86, 0x40,
+       0x46, 0xbb, 0xe5, 0x45, 0x88, 0xfe, 0xc9, 0x63,
+       0x15, 0xfb, 0xf5, 0xbd, 0x71, 0x61, 0xeb, 0x7b,
+       0x78, 0x70, 0x07, 0x31, 0x03, 0x9f, 0xb2, 0xc8,
+       0xa7, 0xab, 0x47, 0xfd, 0xdf, 0xa0, 0x78, 0x72,
+       0xa4, 0x2a, 0xe4, 0xb6, 0xba, 0xc0, 0x1e, 0x86,
+       0x71, 0xe6, 0x3d, 0x18, 0x37, 0x70, 0xe6, 0xff,
+       0xe0, 0xbc, 0x0b, 0x22, 0xa0, 0x1f, 0xd3, 0xed,
+       0xa2, 0x55, 0x39, 0xab, 0xa8, 0x13, 0x73, 0x7c,
+       0x3f, 0xb2, 0xd6, 0x19, 0xac, 0xff, 0x99, 0xed,
+       0xe8, 0xe6, 0xa6, 0x22, 0xe3, 0x9c, 0xf1, 0x30,
+       0xdc, 0x01, 0x0a, 0x56, 0xfa, 0xe4, 0xc9, 0x99,
+       0xdd, 0xa8, 0xd8, 0xda, 0x35, 0x51, 0x73, 0xb4,
+       0x40, 0x86, 0x85, 0xdb, 0x5c, 0xd5, 0x85, 0x80,
+       0x14, 0x9c, 0xfd, 0x98, 0xa9, 0x82, 0xc5, 0x37,
+       0xff, 0x32, 0x5d, 0xd0, 0x0b, 0xfa, 0xdc, 0x04,
+       0x5e, 0x09, 0xd2, 0xca, 0x17, 0x4b, 0x1a, 0x8e,
+       0x15, 0xe1, 0xcc, 0x4e, 0x52, 0x88, 0x35, 0xbd,
+       0x48, 0xfe, 0x15, 0xa0, 0x91, 0xfd, 0x7e, 0x6c,
+       0x0e, 0x5d, 0x79, 0x1b, 0x81, 0x79, 0xd2, 0x09,
+       0x34, 0x70, 0x3d, 0x81, 0xec, 0xf6, 0x24, 0xbb,
+       0xfb, 0xf1, 0x7b, 0xdf, 0x54, 0xea, 0x80, 0x9b,
+       0xc7, 0x99, 0x9e, 0xbd, 0x16, 0x78, 0x12, 0x53,
+       0x5e, 0x01, 0xa7, 0x4e, 0xbd, 0x67, 0xe1, 0x9b,
+       0x4c, 0x0e, 0x61, 0x45, 0x97, 0xd2, 0xf0, 0x0f,
+       0xfe, 0x15, 0x08, 0xb7, 0x11, 0x4c, 0xe7, 0xff,
+       0x81, 0x53, 0xff, 0x91, 0x25, 0x38, 0x7e, 0x40,
+       0x94, 0xe5, 0xe0, 0xad, 0xe6, 0xd9, 0x79, 0xb6,
+       0x92, 0xc9, 0xfc, 0xde, 0xc3, 0x1a, 0x23, 0xbb,
+       0xdd, 0xc8, 0x51, 0x0c, 0x3a, 0x72, 0xfa, 0x73,
+       0x6f, 0xb7, 0xee, 0x61, 0x39, 0x03, 0x01, 0x3f,
+       0x7f, 0x94, 0x2e, 0x2e, 0xba, 0x3a, 0xbb, 0xb4,
+       0xfa, 0x6a, 0x17, 0xfe, 0xea, 0xef, 0x5e, 0x66,
+       0x97, 0x3f, 0x32, 0x3d, 0xd7, 0x3e, 0xb1, 0xf1,
+       0x6c, 0x14, 0x4c, 0xfd, 0x37, 0xd3, 0x38, 0x80,
+       0xfb, 0xde, 0xa6, 0x24, 0x1e, 0xc8, 0xca, 0x7f,
+       0x3a, 0x93, 0xd8, 0x8b, 0x18, 0x13, 0xb2, 0xe5,
+       0xe4, 0x93, 0x05, 0x53, 0x4f, 0x84, 0x66, 0xa7,
+       0x58, 0x5c, 0x7b, 0x86, 0x52, 0x6d, 0x0d, 0xce,
+       0xa4, 0x30, 0x7d, 0xb6, 0x18, 0x9f, 0xeb, 0xff,
+       0x22, 0xbb, 0x72, 0x29, 0xb9, 0x44, 0x0b, 0x48,
+       0x1e, 0x84, 0x71, 0x81, 0xe3, 0x6d, 0x73, 0x26,
+       0x92, 0xb4, 0x4d, 0x2a, 0x29, 0xb8, 0x1f, 0x72,
+       0xed, 0xd0, 0xe1, 0x64, 0x77, 0xea, 0x8e, 0x88,
+       0x0f, 0xef, 0x3f, 0xb1, 0x3b, 0xad, 0xf9, 0xc9,
+       0x8b, 0xd0, 0xac, 0xc6, 0xcc, 0xa9, 0x40, 0xcc,
+       0x76, 0xf6, 0x3b, 0x53, 0xb5, 0x88, 0xcb, 0xc8,
+       0x37, 0xf1, 0xa2, 0xba, 0x23, 0x15, 0x99, 0x09,
+       0xcc, 0xe7, 0x7a, 0x3b, 0x37, 0xf7, 0x58, 0xc8,
+       0x46, 0x8c, 0x2b, 0x2f, 0x4e, 0x0e, 0xa6, 0x5c,
+       0xea, 0x85, 0x55, 0xba, 0x02, 0x0e, 0x0e, 0x48,
+       0xbc, 0xe1, 0xb1, 0x01, 0x35, 0x79, 0x13, 0x3d,
+       0x1b, 0xc0, 0x53, 0x68, 0x11, 0xe7, 0x95, 0x0f,
+       0x9d, 0x3f, 0x4c, 0x47, 0x7b, 0x4d, 0x1c, 0xae,
+       0x50, 0x9b, 0xcb, 0xdd, 0x05, 0x8d, 0x9a, 0x97,
+       0xfd, 0x8c, 0xef, 0x0c, 0x1d, 0x67, 0x73, 0xa8,
+       0x28, 0x36, 0xd5, 0xb6, 0x92, 0x33, 0x40, 0x75,
+       0x0b, 0x51, 0xc3, 0x64, 0xba, 0x1d, 0xc2, 0xcc,
+       0xee, 0x7d, 0x54, 0x0f, 0x27, 0x69, 0xa7, 0x27,
+       0x63, 0x30, 0x29, 0xd9, 0xc8, 0x84, 0xd8, 0xdf,
+       0x9f, 0x68, 0x8d, 0x04, 0xca, 0xa6, 0xc5, 0xc7,
+       0x7a, 0x5c, 0xc8, 0xd1, 0xcb, 0x4a, 0xec, 0xd0,
+       0xd8, 0x20, 0x69, 0xc5, 0x17, 0xcd, 0x78, 0xc8,
+       0x75, 0x23, 0x30, 0x69, 0xc9, 0xd4, 0xea, 0x5c,
+       0x4f, 0x6b, 0x86, 0x3f, 0x8b, 0xfe, 0xee, 0x44,
+       0xc9, 0x7c, 0xb7, 0xdd, 0x3e, 0xe5, 0xec, 0x54,
+       0x03, 0x3e, 0xaa, 0x82, 0xc6, 0xdf, 0xb2, 0x38,
+       0x0e, 0x5d, 0xb3, 0x88, 0xd9, 0xd3, 0x69, 0x5f,
+       0x8f, 0x70, 0x8a, 0x7e, 0x11, 0xd9, 0x1e, 0x7b,
+       0x38, 0xf1, 0x42, 0x1a, 0xc0, 0x35, 0xf5, 0xc7,
+       0x36, 0x85, 0xf5, 0xf7, 0xb8, 0x7e, 0xc7, 0xef,
+       0x18, 0xf1, 0x63, 0xd6, 0x7a, 0xc6, 0xc9, 0x0e,
+       0x4d, 0x69, 0x4f, 0x84, 0xef, 0x26, 0x41, 0x0c,
+       0xec, 0xc7, 0xe0, 0x7e, 0x3c, 0x67, 0x01, 0x4c,
+       0x62, 0x1a, 0x20, 0x6f, 0xee, 0x47, 0x4d, 0xc0,
+       0x99, 0x13, 0x8d, 0x91, 0x4a, 0x26, 0xd4, 0x37,
+       0x28, 0x90, 0x58, 0x75, 0x66, 0x2b, 0x0a, 0xdf,
+       0xda, 0xee, 0x92, 0x25, 0x90, 0x62, 0x39, 0x9e,
+       0x44, 0x98, 0xad, 0xc1, 0x88, 0xed, 0xe4, 0xb4,
+       0xaf, 0xf5, 0x8c, 0x9b, 0x48, 0x4d, 0x56, 0x60,
+       0x97, 0x0f, 0x61, 0x59, 0x9e, 0xa6, 0x27, 0xfe,
+       0xc1, 0x91, 0x15, 0x38, 0xb8, 0x0f, 0xae, 0x61,
+       0x7d, 0x26, 0x13, 0x5a, 0x73, 0xff, 0x1c, 0xa3,
+       0x61, 0x04, 0x58, 0x48, 0x55, 0x44, 0x11, 0xfe,
+       0x15, 0xca, 0xc3, 0xbd, 0xca, 0xc5, 0xb4, 0x40,
+       0x5d, 0x1b, 0x7f, 0x39, 0xb5, 0x9c, 0x35, 0xec,
+       0x61, 0x15, 0x32, 0x32, 0xb8, 0x4e, 0x40, 0x9f,
+       0x17, 0x1f, 0x0a, 0x4d, 0xa9, 0x91, 0xef, 0xb7,
+       0xb0, 0xeb, 0xc2, 0x83, 0x9a, 0x6c, 0xd2, 0x79,
+       0x43, 0x78, 0x5e, 0x2f, 0xe5, 0xdd, 0x1a, 0x3c,
+       0x45, 0xab, 0x29, 0x40, 0x3a, 0x37, 0x5b, 0x6f,
+       0xd7, 0xfc, 0x48, 0x64, 0x3c, 0x49, 0xfb, 0x21,
+       0xbe, 0xc3, 0xff, 0x07, 0xfb, 0x17, 0xe9, 0xc9,
+       0x0c, 0x4c, 0x5c, 0x15, 0x9e, 0x8e, 0x22, 0x30,
+       0x0a, 0xde, 0x48, 0x7f, 0xdb, 0x0d, 0xd1, 0x2b,
+       0x87, 0x38, 0x9e, 0xcc, 0x5a, 0x01, 0x16, 0xee,
+       0x75, 0x49, 0x0d, 0x30, 0x01, 0x34, 0x6a, 0xb6,
+       0x9a, 0x5a, 0x2a, 0xec, 0xbb, 0x48, 0xac, 0xd3,
+       0x77, 0x83, 0xd8, 0x08, 0x86, 0x4f, 0x48, 0x09,
+       0x29, 0x41, 0x79, 0xa1, 0x03, 0x12, 0xc4, 0xcd,
+       0x90, 0x55, 0x47, 0x66, 0x74, 0x9a, 0xcc, 0x4f,
+       0x35, 0x8c, 0xd6, 0x98, 0xef, 0xeb, 0x45, 0xb9,
+       0x9a, 0x26, 0x2f, 0x39, 0xa5, 0x70, 0x6d, 0xfc,
+       0xb4, 0x51, 0xee, 0xf4, 0x9c, 0xe7, 0x38, 0x59,
+       0xad, 0xf4, 0xbc, 0x46, 0xff, 0x46, 0x8e, 0x60,
+       0x9c, 0xa3, 0x60, 0x1d, 0xf8, 0x26, 0x72, 0xf5,
+       0x72, 0x9d, 0x68, 0x80, 0x04, 0xf6, 0x0b, 0xa1,
+       0x0a, 0xd5, 0xa7, 0x82, 0x3a, 0x3e, 0x47, 0xa8,
+       0x5a, 0xde, 0x59, 0x4f, 0x7b, 0x07, 0xb3, 0xe9,
+       0x24, 0x19, 0x3d, 0x34, 0x05, 0xec, 0xf1, 0xab,
+       0x6e, 0x64, 0x8f, 0xd3, 0xe6, 0x41, 0x86, 0x80,
+       0x70, 0xe3, 0x8d, 0x60, 0x9c, 0x34, 0x25, 0x01,
+       0x07, 0x4d, 0x19, 0x41, 0x4e, 0x3d, 0x5c, 0x7e,
+       0xa8, 0xf5, 0xcc, 0xd5, 0x7b, 0xe2, 0x7d, 0x3d,
+       0x49, 0x86, 0x7d, 0x07, 0xb7, 0x10, 0xe3, 0x35,
+       0xb8, 0x84, 0x6d, 0x76, 0xab, 0x17, 0xc6, 0x38,
+       0xb4, 0xd3, 0x28, 0x57, 0xad, 0xd3, 0x88, 0x5a,
+       0xda, 0xea, 0xc8, 0x94, 0xcc, 0x37, 0x19, 0xac,
+       0x9c, 0x9f, 0x4b, 0x00, 0x15, 0xc0, 0xc8, 0xca,
+       0x1f, 0x15, 0xaa, 0xe0, 0xdb, 0xf9, 0x2f, 0x57,
+       0x1b, 0x24, 0xc7, 0x6f, 0x76, 0x29, 0xfb, 0xed,
+       0x25, 0x0d, 0xc0, 0xfe, 0xbd, 0x5a, 0xbf, 0x20,
+       0x08, 0x51, 0x05, 0xec, 0x71, 0xa3, 0xbf, 0xef,
+       0x5e, 0x99, 0x75, 0xdb, 0x3c, 0x5f, 0x9a, 0x8c,
+       0xbb, 0x19, 0x5c, 0x0e, 0x93, 0x19, 0xf8, 0x6a,
+       0xbc, 0xf2, 0x12, 0x54, 0x2f, 0xcb, 0x28, 0x64,
+       0x88, 0xb3, 0x92, 0x0d, 0x96, 0xd1, 0xa6, 0xe4,
+       0x1f, 0xf1, 0x4d, 0xa4, 0xab, 0x1c, 0xee, 0x54,
+       0xf2, 0xad, 0x29, 0x6d, 0x32, 0x37, 0xb2, 0x16,
+       0x77, 0x5c, 0xdc, 0x2e, 0x54, 0xec, 0x75, 0x26,
+       0xc6, 0x36, 0xd9, 0x17, 0x2c, 0xf1, 0x7a, 0xdc,
+       0x4b, 0xf1, 0xe2, 0xd9, 0x95, 0xba, 0xac, 0x87,
+       0xc1, 0xf3, 0x8e, 0x58, 0x08, 0xd8, 0x87, 0x60,
+       0xc9, 0xee, 0x6a, 0xde, 0xa4, 0xd2, 0xfc, 0x0d,
+       0xe5, 0x36, 0xc4, 0x5c, 0x52, 0xb3, 0x07, 0x54,
+       0x65, 0x24, 0xc1, 0xb1, 0xd1, 0xb1, 0x53, 0x13,
+       0x31, 0x79, 0x7f, 0x05, 0x76, 0xeb, 0x37, 0x59,
+       0x15, 0x2b, 0xd1, 0x3f, 0xac, 0x08, 0x97, 0xeb,
+       0x91, 0x98, 0xdf, 0x6c, 0x09, 0x0d, 0x04, 0x9f,
+       0xdc, 0x3b, 0x0e, 0x60, 0x68, 0x47, 0x23, 0x15,
+       0x16, 0xc6, 0x0b, 0x35, 0xf8, 0x77, 0xa2, 0x78,
+       0x50, 0xd4, 0x64, 0x22, 0x33, 0xff, 0xfb, 0x93,
+       0x71, 0x46, 0x50, 0x39, 0x1b, 0x9c, 0xea, 0x4e,
+       0x8d, 0x0c, 0x37, 0xe5, 0x5c, 0x51, 0x3a, 0x31,
+       0xb2, 0x85, 0x84, 0x3f, 0x41, 0xee, 0xa2, 0xc1,
+       0xc6, 0x13, 0x3b, 0x54, 0x28, 0xd2, 0x18, 0x37,
+       0xcc, 0x46, 0x9f, 0x6a, 0x91, 0x3d, 0x5a, 0x15,
+       0x3c, 0x89, 0xa3, 0x61, 0x06, 0x7d, 0x2e, 0x78,
+       0xbe, 0x7d, 0x40, 0xba, 0x2f, 0x95, 0xb1, 0x2f,
+       0x87, 0x3b, 0x8a, 0xbe, 0x6a, 0xf4, 0xc2, 0x31,
+       0x74, 0xee, 0x91, 0xe0, 0x23, 0xaa, 0x5d, 0x7f,
+       0xdd, 0xf0, 0x44, 0x8c, 0x0b, 0x59, 0x2b, 0xfc,
+       0x48, 0x3a, 0xdf, 0x07, 0x05, 0x38, 0x6c, 0xc9,
+       0xeb, 0x18, 0x24, 0x68, 0x8d, 0x58, 0x98, 0xd3,
+       0x31, 0xa3, 0xe4, 0x70, 0x59, 0xb1, 0x21, 0xbe,
+       0x7e, 0x65, 0x7d, 0xb8, 0x04, 0xab, 0xf6, 0xe4,
+       0xd7, 0xda, 0xec, 0x09, 0x8f, 0xda, 0x6d, 0x24,
+       0x07, 0xcc, 0x29, 0x17, 0x05, 0x78, 0x1a, 0xc1,
+       0xb1, 0xce, 0xfc, 0xaa, 0x2d, 0xe7, 0xcc, 0x85,
+       0x84, 0x84, 0x03, 0x2a, 0x0c, 0x3f, 0xa9, 0xf8,
+       0xfd, 0x84, 0x53, 0x59, 0x5c, 0xf0, 0xd4, 0x09,
+       0xf0, 0xd2, 0x6c, 0x32, 0x03, 0xb0, 0xa0, 0x8c,
+       0x52, 0xeb, 0x23, 0x91, 0x88, 0x43, 0x13, 0x46,
+       0xf6, 0x1e, 0xb4, 0x1b, 0xf5, 0x8e, 0x3a, 0xb5,
+       0x3d, 0x00, 0xf6, 0xe5, 0x08, 0x3d, 0x5f, 0x39,
+       0xd3, 0x21, 0x69, 0xbc, 0x03, 0x22, 0x3a, 0xd2,
+       0x5c, 0x84, 0xf8, 0x15, 0xc4, 0x80, 0x0b, 0xbc,
+       0x29, 0x3c, 0xf3, 0x95, 0x98, 0xcd, 0x8f, 0x35,
+       0xbc, 0xa5, 0x3e, 0xfc, 0xd4, 0x13, 0x9e, 0xde,
+       0x4f, 0xce, 0x71, 0x9d, 0x09, 0xad, 0xf2, 0x80,
+       0x6b, 0x65, 0x7f, 0x03, 0x00, 0x14, 0x7c, 0x15,
+       0x85, 0x40, 0x6d, 0x70, 0xea, 0xdc, 0xb3, 0x63,
+       0x35, 0x4f, 0x4d, 0xe0, 0xd9, 0xd5, 0x3c, 0x58,
+       0x56, 0x23, 0x80, 0xe2, 0x36, 0xdd, 0x75, 0x1d,
+       0x94, 0x11, 0x41, 0x8e, 0xe0, 0x81, 0x8e, 0xcf,
+       0xe0, 0xe5, 0xf6, 0xde, 0xd1, 0xe7, 0x04, 0x12,
+       0x79, 0x92, 0x2b, 0x71, 0x2a, 0x79, 0x8b, 0x7c,
+       0x44, 0x79, 0x16, 0x30, 0x4e, 0xf4, 0xf6, 0x9b,
+       0xb7, 0x40, 0xa3, 0x5a, 0xa7, 0x69, 0x3e, 0xc1,
+       0x3a, 0x04, 0xd0, 0x88, 0xa0, 0x3b, 0xdd, 0xc6,
+       0x9e, 0x7e, 0x1e, 0x1e, 0x8f, 0x44, 0xf7, 0x73,
+       0x67, 0x1e, 0x1a, 0x78, 0xfa, 0x62, 0xf4, 0xa9,
+       0xa8, 0xc6, 0x5b, 0xb8, 0xfa, 0x06, 0x7d, 0x5e,
+       0x38, 0x1c, 0x9a, 0x39, 0xe9, 0x39, 0x98, 0x22,
+       0x0b, 0xa7, 0xac, 0x0b, 0xf3, 0xbc, 0xf1, 0xeb,
+       0x8c, 0x81, 0xe3, 0x48, 0x8a, 0xed, 0x42, 0xc2,
+       0x38, 0xcf, 0x3e, 0xda, 0xd2, 0x89, 0x8d, 0x9c,
+       0x53, 0xb5, 0x2f, 0x41, 0x01, 0x26, 0x84, 0x9c,
+       0xa3, 0x56, 0xf6, 0x49, 0xc7, 0xd4, 0x9f, 0x93,
+       0x1b, 0x96, 0x49, 0x5e, 0xad, 0xb3, 0x84, 0x1f,
+       0x3c, 0xa4, 0xe0, 0x9b, 0xd1, 0x90, 0xbc, 0x38,
+       0x6c, 0xdd, 0x95, 0x4d, 0x9d, 0xb1, 0x71, 0x57,
+       0x2d, 0x34, 0xe8, 0xb8, 0x42, 0xc7, 0x99, 0x03,
+       0xc7, 0x07, 0x30, 0x65, 0x91, 0x55, 0xd5, 0x90,
+       0x70, 0x97, 0x37, 0x68, 0xd4, 0x11, 0xf9, 0xe8,
+       0xce, 0xec, 0xdc, 0x34, 0xd5, 0xd3, 0xb7, 0xc4,
+       0xb8, 0x97, 0x05, 0x92, 0xad, 0xf8, 0xe2, 0x36,
+       0x64, 0x41, 0xc9, 0xc5, 0x41, 0x77, 0x52, 0xd7,
+       0x2c, 0xa5, 0x24, 0x2f, 0xd9, 0x34, 0x0b, 0x47,
+       0x35, 0xa7, 0x28, 0x8b, 0xc5, 0xcd, 0xe9, 0x46,
+       0xac, 0x39, 0x94, 0x3c, 0x10, 0xc6, 0x29, 0x73,
+       0x0e, 0x0e, 0x5d, 0xe0, 0x71, 0x03, 0x8a, 0x72,
+       0x0e, 0x26, 0xb0, 0x7d, 0x84, 0xed, 0x95, 0x23,
+       0x49, 0x5a, 0x45, 0x83, 0x45, 0x60, 0x11, 0x4a,
+       0x46, 0x31, 0xd4, 0xd8, 0x16, 0x54, 0x98, 0x58,
+       0xed, 0x6d, 0xcc, 0x5d, 0xd6, 0x50, 0x61, 0x9f,
+       0x9d, 0xc5, 0x3e, 0x9d, 0x32, 0x47, 0xde, 0x96,
+       0xe1, 0x5d, 0xd8, 0xf8, 0xb4, 0x69, 0x6f, 0xb9,
+       0x15, 0x90, 0x57, 0x7a, 0xf6, 0xad, 0xb0, 0x5b,
+       0xf5, 0xa6, 0x36, 0x94, 0xfd, 0x84, 0xce, 0x1c,
+       0x0f, 0x4b, 0xd0, 0xc2, 0x5b, 0x6b, 0x56, 0xef,
+       0x73, 0x93, 0x0b, 0xc3, 0xee, 0xd9, 0xcf, 0xd3,
+       0xa4, 0x22, 0x58, 0xcd, 0x50, 0x6e, 0x65, 0xf4,
+       0xe9, 0xb7, 0x71, 0xaf, 0x4b, 0xb3, 0xb6, 0x2f,
+       0x0f, 0x0e, 0x3b, 0xc9, 0x85, 0x14, 0xf5, 0x17,
+       0xe8, 0x7a, 0x3a, 0xbf, 0x5f, 0x5e, 0xf8, 0x18,
+       0x48, 0xa6, 0x72, 0xab, 0x06, 0x95, 0xe9, 0xc8,
+       0xa7, 0xf4, 0x32, 0x44, 0x04, 0x0c, 0x84, 0x98,
+       0x73, 0xe3, 0x89, 0x8d, 0x5f, 0x7e, 0x4a, 0x42,
+       0x8f, 0xc5, 0x28, 0xb1, 0x82, 0xef, 0x1c, 0x97,
+       0x31, 0x3b, 0x4d, 0xe0, 0x0e, 0x10, 0x10, 0x97,
+       0x93, 0x49, 0x78, 0x2f, 0x0d, 0x86, 0x8b, 0xa1,
+       0x53, 0xa9, 0x81, 0x20, 0x79, 0xe7, 0x07, 0x77,
+       0xb6, 0xac, 0x5e, 0xd2, 0x05, 0xcd, 0xe9, 0xdb,
+       0x8a, 0x94, 0x82, 0x8a, 0x23, 0xb9, 0x3d, 0x1c,
+       0xa9, 0x7d, 0x72, 0x4a, 0xed, 0x33, 0xa3, 0xdb,
+       0x21, 0xa7, 0x86, 0x33, 0x45, 0xa5, 0xaa, 0x56,
+       0x45, 0xb5, 0x83, 0x29, 0x40, 0x47, 0x79, 0x04,
+       0x6e, 0xb9, 0x95, 0xd0, 0x81, 0x77, 0x2d, 0x48,
+       0x1e, 0xfe, 0xc3, 0xc2, 0x1e, 0xe5, 0xf2, 0xbe,
+       0xfd, 0x3b, 0x94, 0x9f, 0xc4, 0xc4, 0x26, 0x9d,
+       0xe4, 0x66, 0x1e, 0x19, 0xee, 0x6c, 0x79, 0x97,
+       0x11, 0x31, 0x4b, 0x0d, 0x01, 0xcb, 0xde, 0xa8,
+       0xf6, 0x6d, 0x7c, 0x39, 0x46, 0x4e, 0x7e, 0x3f,
+       0x94, 0x17, 0xdf, 0xa1, 0x7d, 0xd9, 0x1c, 0x8e,
+       0xbc, 0x7d, 0x33, 0x7d, 0xe3, 0x12, 0x40, 0xca,
+       0xab, 0x37, 0x11, 0x46, 0xd4, 0xae, 0xef, 0x44,
+       0xa2, 0xb3, 0x6a, 0x66, 0x0e, 0x0c, 0x90, 0x7f,
+       0xdf, 0x5c, 0x66, 0x5f, 0xf2, 0x94, 0x9f, 0xa6,
+       0x73, 0x4f, 0xeb, 0x0d, 0xad, 0xbf, 0xc0, 0x63,
+       0x5c, 0xdc, 0x46, 0x51, 0xe8, 0x8e, 0x90, 0x19,
+       0xa8, 0xa4, 0x3c, 0x91, 0x79, 0xfa, 0x7e, 0x58,
+       0x85, 0x13, 0x55, 0xc5, 0x19, 0x82, 0x37, 0x1b,
+       0x0a, 0x02, 0x1f, 0x99, 0x6b, 0x18, 0xf1, 0x28,
+       0x08, 0xa2, 0x73, 0xb8, 0x0f, 0x2e, 0xcd, 0xbf,
+       0xf3, 0x86, 0x7f, 0xea, 0xef, 0xd0, 0xbb, 0xa6,
+       0x21, 0xdf, 0x49, 0x73, 0x51, 0xcc, 0x36, 0xd3,
+       0x3e, 0xa0, 0xf8, 0x44, 0xdf, 0xd3, 0xa6, 0xbe,
+       0x8a, 0xd4, 0x57, 0xdd, 0x72, 0x94, 0x61, 0x0f,
+       0x82, 0xd1, 0x07, 0xb8, 0x7c, 0x18, 0x83, 0xdf,
+       0x3a, 0xe5, 0x50, 0x6a, 0x82, 0x20, 0xac, 0xa9,
+       0xa8, 0xff, 0xd9, 0xf3, 0x77, 0x33, 0x5a, 0x9e,
+       0x7f, 0x6d, 0xfe, 0x5d, 0x33, 0x41, 0x42, 0xe7,
+       0x6c, 0x19, 0xe0, 0x44, 0x8a, 0x15, 0xf6, 0x70,
+       0x98, 0xb7, 0x68, 0x4d, 0xfa, 0x97, 0x39, 0xb0,
+       0x8e, 0xe8, 0x84, 0x8b, 0x75, 0x30, 0xb7, 0x7d,
+       0x92, 0x69, 0x20, 0x9c, 0x81, 0xfb, 0x4b, 0xf4,
+       0x01, 0x50, 0xeb, 0xce, 0x0c, 0x1c, 0x6c, 0xb5,
+       0x4a, 0xd7, 0x27, 0x0c, 0xce, 0xbb, 0xe5, 0x85,
+       0xf0, 0xb6, 0xee, 0xd5, 0x70, 0xdd, 0x3b, 0xfc,
+       0xd4, 0x99, 0xf1, 0x33, 0xdd, 0x8b, 0xc4, 0x2f,
+       0xae, 0xab, 0x74, 0x96, 0x32, 0xc7, 0x4c, 0x56,
+       0x3c, 0x89, 0x0f, 0x96, 0x0b, 0x42, 0xc0, 0xcb,
+       0xee, 0x0f, 0x0b, 0x8c, 0xfb, 0x7e, 0x47, 0x7b,
+       0x64, 0x48, 0xfd, 0xb2, 0x00, 0x80, 0x89, 0xa5,
+       0x13, 0x55, 0x62, 0xfc, 0x8f, 0xe2, 0x42, 0x03,
+       0xb7, 0x4e, 0x2a, 0x79, 0xb4, 0x82, 0xea, 0x23,
+       0x49, 0xda, 0xaf, 0x52, 0x63, 0x1e, 0x60, 0x03,
+       0x89, 0x06, 0x44, 0x46, 0x08, 0xc3, 0xc4, 0x87,
+       0x70, 0x2e, 0xda, 0x94, 0xad, 0x6b, 0xe0, 0xe4,
+       0xd1, 0x8a, 0x06, 0xc2, 0xa8, 0xc0, 0xa7, 0x43,
+       0x3c, 0x47, 0x52, 0x0e, 0xc3, 0x77, 0x81, 0x11,
+       0x67, 0x0e, 0xa0, 0x70, 0x04, 0x47, 0x29, 0x40,
+       0x86, 0x0d, 0x34, 0x56, 0xa7, 0xc9, 0x35, 0x59,
+       0x68, 0xdc, 0x93, 0x81, 0x70, 0xee, 0x86, 0xd9,
+       0x80, 0x06, 0x40, 0x4f, 0x1a, 0x0d, 0x40, 0x30,
+       0x0b, 0xcb, 0x96, 0x47, 0xc1, 0xb7, 0x52, 0xfd,
+       0x56, 0xe0, 0x72, 0x4b, 0xfb, 0xbd, 0x92, 0x45,
+       0x61, 0x71, 0xc2, 0x33, 0x11, 0xbf, 0x52, 0x83,
+       0x79, 0x26, 0xe0, 0x49, 0x6b, 0xb7, 0x05, 0x8b,
+       0xe8, 0x0e, 0x87, 0x31, 0xd7, 0x9d, 0x8a, 0xf5,
+       0xc0, 0x5f, 0x2e, 0x58, 0x4a, 0xdb, 0x11, 0xb3,
+       0x6c, 0x30, 0x2a, 0x46, 0x19, 0xe3, 0x27, 0x84,
+       0x1f, 0x63, 0x6e, 0xf6, 0x57, 0xc7, 0xc9, 0xd8,
+       0x5e, 0xba, 0xb3, 0x87, 0xd5, 0x83, 0x26, 0x34,
+       0x21, 0x9e, 0x65, 0xde, 0x42, 0xd3, 0xbe, 0x7b,
+       0xbc, 0x91, 0x71, 0x44, 0x4d, 0x99, 0x3b, 0x31,
+       0xe5, 0x3f, 0x11, 0x4e, 0x7f, 0x13, 0x51, 0x3b,
+       0xae, 0x79, 0xc9, 0xd3, 0x81, 0x8e, 0x25, 0x40,
+       0x10, 0xfc, 0x07, 0x1e, 0xf9, 0x7b, 0x9a, 0x4b,
+       0x6c, 0xe3, 0xb3, 0xad, 0x1a, 0x0a, 0xdd, 0x9e,
+       0x59, 0x0c, 0xa2, 0xcd, 0xae, 0x48, 0x4a, 0x38,
+       0x5b, 0x47, 0x41, 0x94, 0x65, 0x6b, 0xbb, 0xeb,
+       0x5b, 0xe3, 0xaf, 0x07, 0x5b, 0xd4, 0x4a, 0xa2,
+       0xc9, 0x5d, 0x2f, 0x64, 0x03, 0xd7, 0x3a, 0x2c,
+       0x6e, 0xce, 0x76, 0x95, 0xb4, 0xb3, 0xc0, 0xf1,
+       0xe2, 0x45, 0x73, 0x7a, 0x5c, 0xab, 0xc1, 0xfc,
+       0x02, 0x8d, 0x81, 0x29, 0xb3, 0xac, 0x07, 0xec,
+       0x40, 0x7d, 0x45, 0xd9, 0x7a, 0x59, 0xee, 0x34,
+       0xf0, 0xe9, 0xd5, 0x7b, 0x96, 0xb1, 0x3d, 0x95,
+       0xcc, 0x86, 0xb5, 0xb6, 0x04, 0x2d, 0xb5, 0x92,
+       0x7e, 0x76, 0xf4, 0x06, 0xa9, 0xa3, 0x12, 0x0f,
+       0xb1, 0xaf, 0x26, 0xba, 0x7c, 0xfc, 0x7e, 0x1c,
+       0xbc, 0x2c, 0x49, 0x97, 0x53, 0x60, 0x13, 0x0b,
+       0xa6, 0x61, 0x83, 0x89, 0x42, 0xd4, 0x17, 0x0c,
+       0x6c, 0x26, 0x52, 0xc3, 0xb3, 0xd4, 0x67, 0xf5,
+       0xe3, 0x04, 0xb7, 0xf4, 0xcb, 0x80, 0xb8, 0xcb,
+       0x77, 0x56, 0x3e, 0xaa, 0x57, 0x54, 0xee, 0xb4,
+       0x2c, 0x67, 0xcf, 0xf2, 0xdc, 0xbe, 0x55, 0xf9,
+       0x43, 0x1f, 0x6e, 0x22, 0x97, 0x67, 0x7f, 0xc4,
+       0xef, 0xb1, 0x26, 0x31, 0x1e, 0x27, 0xdf, 0x41,
+       0x80, 0x47, 0x6c, 0xe2, 0xfa, 0xa9, 0x8c, 0x2a,
+       0xf6, 0xf2, 0xab, 0xf0, 0x15, 0xda, 0x6c, 0xc8,
+       0xfe, 0xb5, 0x23, 0xde, 0xa9, 0x05, 0x3f, 0x06,
+       0x54, 0x4c, 0xcd, 0xe1, 0xab, 0xfc, 0x0e, 0x62,
+       0x33, 0x31, 0x73, 0x2c, 0x76, 0xcb, 0xb4, 0x47,
+       0x1e, 0x20, 0xad, 0xd8, 0xf2, 0x31, 0xdd, 0xc4,
+       0x8b, 0x0c, 0x77, 0xbe, 0xe1, 0x8b, 0x26, 0x00,
+       0x02, 0x58, 0xd6, 0x8d, 0xef, 0xad, 0x74, 0x67,
+       0xab, 0x3f, 0xef, 0xcb, 0x6f, 0xb0, 0xcc, 0x81,
+       0x44, 0x4c, 0xaf, 0xe9, 0x49, 0x4f, 0xdb, 0xa0,
+       0x25, 0xa4, 0xf0, 0x89, 0xf1, 0xbe, 0xd8, 0x10,
+       0xff, 0xb1, 0x3b, 0x4b, 0xfa, 0x98, 0xf5, 0x79,
+       0x6d, 0x1e, 0x69, 0x4d, 0x57, 0xb1, 0xc8, 0x19,
+       0x1b, 0xbd, 0x1e, 0x8c, 0x84, 0xb7, 0x7b, 0xe8,
+       0xd2, 0x2d, 0x09, 0x41, 0x41, 0x37, 0x3d, 0xb1,
+       0x6f, 0x26, 0x5d, 0x71, 0x16, 0x3d, 0xb7, 0x83,
+       0x27, 0x2c, 0xa7, 0xb6, 0x50, 0xbd, 0x91, 0x86,
+       0xab, 0x24, 0xa1, 0x38, 0xfd, 0xea, 0x71, 0x55,
+       0x7e, 0x9a, 0x07, 0x77, 0x4b, 0xfa, 0x61, 0x66,
+       0x20, 0x1e, 0x28, 0x95, 0x18, 0x1b, 0xa4, 0xa0,
+       0xfd, 0xc0, 0x89, 0x72, 0x43, 0xd9, 0x3b, 0x49,
+       0x5a, 0x3f, 0x9d, 0xbf, 0xdb, 0xb4, 0x46, 0xea,
+       0x42, 0x01, 0x77, 0x23, 0x68, 0x95, 0xb6, 0x24,
+       0xb3, 0xa8, 0x6c, 0x28, 0x3b, 0x11, 0x40, 0x7e,
+       0x18, 0x65, 0x6d, 0xd8, 0x24, 0x42, 0x7d, 0x88,
+       0xc0, 0x52, 0xd9, 0x05, 0xe4, 0x95, 0x90, 0x87,
+       0x8c, 0xf4, 0xd0, 0x6b, 0xb9, 0x83, 0x99, 0x34,
+       0x6d, 0xfe, 0x54, 0x40, 0x94, 0x52, 0x21, 0x4f,
+       0x14, 0x25, 0xc5, 0xd6, 0x5e, 0x95, 0xdc, 0x0a,
+       0x2b, 0x89, 0x20, 0x11, 0x84, 0x48, 0xd6, 0x3a,
+       0xcd, 0x5c, 0x24, 0xad, 0x62, 0xe3, 0xb1, 0x93,
+       0x25, 0x8d, 0xcd, 0x7e, 0xfc, 0x27, 0xa3, 0x37,
+       0xfd, 0x84, 0xfc, 0x1b, 0xb2, 0xf1, 0x27, 0x38,
+       0x5a, 0xb7, 0xfc, 0xf2, 0xfa, 0x95, 0x66, 0xd4,
+       0xfb, 0xba, 0xa7, 0xd7, 0xa3, 0x72, 0x69, 0x48,
+       0x48, 0x8c, 0xeb, 0x28, 0x89, 0xfe, 0x33, 0x65,
+       0x5a, 0x36, 0x01, 0x7e, 0x06, 0x79, 0x0a, 0x09,
+       0x3b, 0x74, 0x11, 0x9a, 0x6e, 0xbf, 0xd4, 0x9e,
+       0x58, 0x90, 0x49, 0x4f, 0x4d, 0x08, 0xd4, 0xe5,
+       0x4a, 0x09, 0x21, 0xef, 0x8b, 0xb8, 0x74, 0x3b,
+       0x91, 0xdd, 0x36, 0x85, 0x60, 0x2d, 0xfa, 0xd4,
+       0x45, 0x7b, 0x45, 0x53, 0xf5, 0x47, 0x87, 0x7e,
+       0xa6, 0x37, 0xc8, 0x78, 0x7a, 0x68, 0x9d, 0x8d,
+       0x65, 0x2c, 0x0e, 0x91, 0x5c, 0xa2, 0x60, 0xf0,
+       0x8e, 0x3f, 0xe9, 0x1a, 0xcd, 0xaa, 0xe7, 0xd5,
+       0x77, 0x18, 0xaf, 0xc9, 0xbc, 0x18, 0xea, 0x48,
+       0x1b, 0xfb, 0x22, 0x48, 0x70, 0x16, 0x29, 0x9e,
+       0x5b, 0xc1, 0x2c, 0x66, 0x23, 0xbc, 0xf0, 0x1f,
+       0xef, 0xaf, 0xe4, 0xd6, 0x04, 0x19, 0x82, 0x7a,
+       0x0b, 0xba, 0x4b, 0x46, 0xb1, 0x6a, 0x85, 0x5d,
+       0xb4, 0x73, 0xd6, 0x21, 0xa1, 0x71, 0x60, 0x14,
+       0xee, 0x0a, 0x77, 0xc4, 0x66, 0x2e, 0xf9, 0x69,
+       0x30, 0xaf, 0x41, 0x0b, 0xc8, 0x83, 0x3c, 0x53,
+       0x99, 0x19, 0x27, 0x46, 0xf7, 0x41, 0x6e, 0x56,
+       0xdc, 0x94, 0x28, 0x67, 0x4e, 0xb7, 0x25, 0x48,
+       0x8a, 0xc2, 0xe0, 0x60, 0x96, 0xcc, 0x18, 0xf4,
+       0x84, 0xdd, 0xa7, 0x5e, 0x3e, 0x05, 0x0b, 0x26,
+       0x26, 0xb2, 0x5c, 0x1f, 0x57, 0x1a, 0x04, 0x7e,
+       0x6a, 0xe3, 0x2f, 0xb4, 0x35, 0xb6, 0x38, 0x40,
+       0x40, 0xcd, 0x6f, 0x87, 0x2e, 0xef, 0xa3, 0xd7,
+       0xa9, 0xc2, 0xe8, 0x0d, 0x27, 0xdf, 0x44, 0x62,
+       0x99, 0xa0, 0xfc, 0xcf, 0x81, 0x78, 0xcb, 0xfe,
+       0xe5, 0xa0, 0x03, 0x4e, 0x6c, 0xd7, 0xf4, 0xaf,
+       0x7a, 0xbb, 0x61, 0x82, 0xfe, 0x71, 0x89, 0xb2,
+       0x22, 0x7c, 0x8e, 0x83, 0x04, 0xce, 0xf6, 0x5d,
+       0x84, 0x8f, 0x95, 0x6a, 0x7f, 0xad, 0xfd, 0x32,
+       0x9c, 0x5e, 0xe4, 0x9c, 0x89, 0x60, 0x54, 0xaa,
+       0x96, 0x72, 0xd2, 0xd7, 0x36, 0x85, 0xa9, 0x45,
+       0xd2, 0x2a, 0xa1, 0x81, 0x49, 0x6f, 0x7e, 0x04,
+       0xfa, 0xe2, 0xfe, 0x90, 0x26, 0x77, 0x5a, 0x33,
+       0xb8, 0x04, 0x9a, 0x7a, 0xe6, 0x4c, 0x4f, 0xad,
+       0x72, 0x96, 0x08, 0x28, 0x58, 0x13, 0xf8, 0xc4,
+       0x1c, 0xf0, 0xc3, 0x45, 0x95, 0x49, 0x20, 0x8c,
+       0x9f, 0x39, 0x70, 0xe1, 0x77, 0xfe, 0xd5, 0x4b,
+       0xaf, 0x86, 0xda, 0xef, 0x22, 0x06, 0x83, 0x36,
+       0x29, 0x12, 0x11, 0x40, 0xbc, 0x3b, 0x86, 0xaa,
+       0xaa, 0x65, 0x60, 0xc3, 0x80, 0xca, 0xed, 0xa9,
+       0xf3, 0xb0, 0x79, 0x96, 0xa2, 0x55, 0x27, 0x28,
+       0x55, 0x73, 0x26, 0xa5, 0x50, 0xea, 0x92, 0x4b,
+       0x3c, 0x5c, 0x82, 0x33, 0xf0, 0x01, 0x3f, 0x03,
+       0xc1, 0x08, 0x05, 0xbf, 0x98, 0xf4, 0x9b, 0x6d,
+       0xa5, 0xa8, 0xb4, 0x82, 0x0c, 0x06, 0xfa, 0xff,
+       0x2d, 0x08, 0xf3, 0x05, 0x4f, 0x57, 0x2a, 0x39,
+       0xd4, 0x83, 0x0d, 0x75, 0x51, 0xd8, 0x5b, 0x1b,
+       0xd3, 0x51, 0x5a, 0x32, 0x2a, 0x9b, 0x32, 0xb2,
+       0xf2, 0xa4, 0x96, 0x12, 0xf2, 0xae, 0x40, 0x34,
+       0x67, 0xa8, 0xf5, 0x44, 0xd5, 0x35, 0x53, 0xfe,
+       0xa3, 0x60, 0x96, 0x63, 0x0f, 0x1f, 0x6e, 0xb0,
+       0x5a, 0x42, 0xa6, 0xfc, 0x51, 0x0b, 0x60, 0x27,
+       0xbc, 0x06, 0x71, 0xed, 0x65, 0x5b, 0x23, 0x86,
+       0x4a, 0x07, 0x3b, 0x22, 0x07, 0x46, 0xe6, 0x90,
+       0x3e, 0xf3, 0x25, 0x50, 0x1b, 0x4c, 0x7f, 0x03,
+       0x08, 0xa8, 0x36, 0x6b, 0x87, 0xe5, 0xe3, 0xdb,
+       0x9a, 0x38, 0x83, 0xff, 0x9f, 0x1a, 0x9f, 0x57,
+       0xa4, 0x2a, 0xf6, 0x37, 0xbc, 0x1a, 0xff, 0xc9,
+       0x1e, 0x35, 0x0c, 0xc3, 0x7c, 0xa3, 0xb2, 0xe5,
+       0xd2, 0xc6, 0xb4, 0x57, 0x47, 0xe4, 0x32, 0x16,
+       0x6d, 0xa9, 0xae, 0x64, 0xe6, 0x2d, 0x8d, 0xc5,
+       0x8d, 0x50, 0x8e, 0xe8, 0x1a, 0x22, 0x34, 0x2a,
+       0xd9, 0xeb, 0x51, 0x90, 0x4a, 0xb1, 0x41, 0x7d,
+       0x64, 0xf9, 0xb9, 0x0d, 0xf6, 0x23, 0x33, 0xb0,
+       0x33, 0xf4, 0xf7, 0x3f, 0x27, 0x84, 0xc6, 0x0f,
+       0x54, 0xa5, 0xc0, 0x2e, 0xec, 0x0b, 0x3a, 0x48,
+       0x6e, 0x80, 0x35, 0x81, 0x43, 0x9b, 0x90, 0xb1,
+       0xd0, 0x2b, 0xea, 0x21, 0xdc, 0xda, 0x5b, 0x09,
+       0xf4, 0xcc, 0x10, 0xb4, 0xc7, 0xfe, 0x79, 0x51,
+       0xc3, 0xc5, 0xac, 0x88, 0x74, 0x84, 0x0b, 0x4b,
+       0xca, 0x79, 0x16, 0x29, 0xfb, 0x69, 0x54, 0xdf,
+       0x41, 0x7e, 0xe9, 0xc7, 0x8e, 0xea, 0xa5, 0xfe,
+       0xfc, 0x76, 0x0e, 0x90, 0xc4, 0x92, 0x38, 0xad,
+       0x7b, 0x48, 0xe6, 0x6e, 0xf7, 0x21, 0xfd, 0x4e,
+       0x93, 0x0a, 0x7b, 0x41, 0x83, 0x68, 0xfb, 0x57,
+       0x51, 0x76, 0x34, 0xa9, 0x6c, 0x00, 0xaa, 0x4f,
+       0x66, 0x65, 0x98, 0x4a, 0x4f, 0xa3, 0xa0, 0xef,
+       0x69, 0x3f, 0xe3, 0x1c, 0x92, 0x8c, 0xfd, 0xd8,
+       0xe8, 0xde, 0x7c, 0x7f, 0x3e, 0x84, 0x8e, 0x69,
+       0x3c, 0xf1, 0xf2, 0x05, 0x46, 0xdc, 0x2f, 0x9d,
+       0x5e, 0x6e, 0x4c, 0xfb, 0xb5, 0x99, 0x2a, 0x59,
+       0x63, 0xc1, 0x34, 0xbc, 0x57, 0xc0, 0x0d, 0xb9,
+       0x61, 0x25, 0xf3, 0x33, 0x23, 0x51, 0xb6, 0x0d,
+       0x07, 0xa6, 0xab, 0x94, 0x4a, 0xb7, 0x2a, 0xea,
+       0xee, 0xac, 0xa3, 0xc3, 0x04, 0x8b, 0x0e, 0x56,
+       0xfe, 0x44, 0xa7, 0x39, 0xe2, 0xed, 0xed, 0xb4,
+       0x22, 0x2b, 0xac, 0x12, 0x32, 0x28, 0x91, 0xd8,
+       0xa5, 0xab, 0xff, 0x5f, 0xe0, 0x4b, 0xda, 0x78,
+       0x17, 0xda, 0xf1, 0x01, 0x5b, 0xcd, 0xe2, 0x5f,
+       0x50, 0x45, 0x73, 0x2b, 0xe4, 0x76, 0x77, 0xf4,
+       0x64, 0x1d, 0x43, 0xfb, 0x84, 0x7a, 0xea, 0x91,
+       0xae, 0xf9, 0x9e, 0xb7, 0xb4, 0xb0, 0x91, 0x5f,
+       0x16, 0x35, 0x9a, 0x11, 0xb8, 0xc7, 0xc1, 0x8c,
+       0xc6, 0x10, 0x8d, 0x2f, 0x63, 0x4a, 0xa7, 0x57,
+       0x3a, 0x51, 0xd6, 0x32, 0x2d, 0x64, 0x72, 0xd4,
+       0x66, 0xdc, 0x10, 0xa6, 0x67, 0xd6, 0x04, 0x23,
+       0x9d, 0x0a, 0x11, 0x77, 0xdd, 0x37, 0x94, 0x17,
+       0x3c, 0xbf, 0x8b, 0x65, 0xb0, 0x2e, 0x5e, 0x66,
+       0x47, 0x64, 0xac, 0xdd, 0xf0, 0x84, 0xfd, 0x39,
+       0xfa, 0x15, 0x5d, 0xef, 0xae, 0xca, 0xc1, 0x36,
+       0xa7, 0x5c, 0xbf, 0xc7, 0x08, 0xc2, 0x66, 0x00,
+       0x74, 0x74, 0x4e, 0x27, 0x3f, 0x55, 0x8a, 0xb7,
+       0x38, 0x66, 0x83, 0x6d, 0xcf, 0x99, 0x9e, 0x60,
+       0x8f, 0xdd, 0x2e, 0x62, 0x22, 0x0e, 0xef, 0x0c,
+       0x98, 0xa7, 0x85, 0x74, 0x3b, 0x9d, 0xec, 0x9e,
+       0xa9, 0x19, 0x72, 0xa5, 0x7f, 0x2c, 0x39, 0xb7,
+       0x7d, 0xb7, 0xf1, 0x12, 0x65, 0x27, 0x4b, 0x5a,
+       0xde, 0x17, 0xfe, 0xad, 0x44, 0xf3, 0x20, 0x4d,
+       0xfd, 0xe4, 0x1f, 0xb5, 0x81, 0xb0, 0x36, 0x37,
+       0x08, 0x6f, 0xc3, 0x0c, 0xe9, 0x85, 0x98, 0x82,
+       0xa9, 0x62, 0x0c, 0xc4, 0x97, 0xc0, 0x50, 0xc8,
+       0xa7, 0x3c, 0x50, 0x9f, 0x43, 0xb9, 0xcd, 0x5e,
+       0x4d, 0xfa, 0x1c, 0x4b, 0x0b, 0xa9, 0x98, 0x85,
+       0x38, 0x92, 0xac, 0x8d, 0xe4, 0xad, 0x9b, 0x98,
+       0xab, 0xd9, 0x38, 0xac, 0x62, 0x52, 0xa3, 0x22,
+       0x63, 0x0f, 0xbf, 0x95, 0x48, 0xdf, 0x69, 0xe7,
+       0x8b, 0x33, 0xd5, 0xb2, 0xbd, 0x05, 0x49, 0x49,
+       0x9d, 0x57, 0x73, 0x19, 0x33, 0xae, 0xfa, 0x33,
+       0xf1, 0x19, 0xa8, 0x80, 0xce, 0x04, 0x9f, 0xbc,
+       0x1d, 0x65, 0x82, 0x1b, 0xe5, 0x3a, 0x51, 0xc8,
+       0x1c, 0x21, 0xe3, 0x5d, 0xf3, 0x7d, 0x9b, 0x2f,
+       0x2c, 0x1d, 0x4a, 0x7f, 0x9b, 0x68, 0x35, 0xa3,
+       0xb2, 0x50, 0xf7, 0x62, 0x79, 0xcd, 0xf4, 0x98,
+       0x4f, 0xe5, 0x63, 0x7c, 0x3e, 0x45, 0x31, 0x8c,
+       0x16, 0xa0, 0x12, 0xc8, 0x58, 0xce, 0x39, 0xa6,
+       0xbc, 0x54, 0xdb, 0xc5, 0xe0, 0xd5, 0xba, 0xbc,
+       0xb9, 0x04, 0xf4, 0x8d, 0xe8, 0x2f, 0x15, 0x9d,
+};
+
+/* 100 test cases */
+static struct dahash_test {
+       uint16_t        start;  /* random 12 bit offset in buf */
+       uint16_t        length; /* random 8 bit length of test */
+       xfs_dahash_t    dahash; /* expected dahash result */
+} test[] __initdata =
+{
+       {0x0567, 0x0097, 0x96951389},
+       {0x0869, 0x0055, 0x6455ab4f},
+       {0x0c51, 0x00be, 0x8663afde},
+       {0x044a, 0x00fc, 0x98fbe432},
+       {0x0f29, 0x0079, 0x42371997},
+       {0x08ba, 0x0052, 0x942be4f7},
+       {0x01f2, 0x0013, 0x5262687e},
+       {0x09e3, 0x00e2, 0x8ffb0908},
+       {0x007c, 0x0051, 0xb3158491},
+       {0x0854, 0x001f, 0x83bb20d9},
+       {0x031b, 0x0008, 0x98970bdf},
+       {0x0de7, 0x0027, 0xbfbf6f6c},
+       {0x0f76, 0x0005, 0x906a7105},
+       {0x092e, 0x00d0, 0x86631850},
+       {0x0233, 0x0082, 0xdbdd914e},
+       {0x04c9, 0x0075, 0x5a400a9e},
+       {0x0b66, 0x0099, 0xae128b45},
+       {0x000d, 0x00ed, 0xe61c216a},
+       {0x0a31, 0x003d, 0xf69663b9},
+       {0x00a3, 0x0052, 0x643c39ae},
+       {0x0125, 0x00d5, 0x7c310b0d},
+       {0x0105, 0x004a, 0x06a77e74},
+       {0x0858, 0x008e, 0x265bc739},
+       {0x045e, 0x0095, 0x13d6b192},
+       {0x0dab, 0x003c, 0xc4498704},
+       {0x00cd, 0x00b5, 0x802a4e2d},
+       {0x069b, 0x008c, 0x5df60f71},
+       {0x0454, 0x006c, 0x5f03d8bb},
+       {0x040e, 0x0032, 0x0ce513b5},
+       {0x0874, 0x00e2, 0x6a811fb3},
+       {0x0521, 0x00b4, 0x93296833},
+       {0x0ddc, 0x00cf, 0xf9305338},
+       {0x0a70, 0x0023, 0x239549ea},
+       {0x083e, 0x0027, 0x2d88ba97},
+       {0x0241, 0x00a7, 0xfe0b32e1},
+       {0x0dfc, 0x0096, 0x1a11e815},
+       {0x023e, 0x001e, 0xebc9a1f3},
+       {0x067e, 0x0066, 0xb1067f81},
+       {0x09ea, 0x000e, 0x46fd7247},
+       {0x036b, 0x008c, 0x1a39acdf},
+       {0x078f, 0x0030, 0x964042ab},
+       {0x085c, 0x008f, 0x1829edab},
+       {0x02ec, 0x009f, 0x6aefa72d},
+       {0x043b, 0x00ce, 0x65642ff5},
+       {0x0a32, 0x00b8, 0xbd82759e},
+       {0x0d3c, 0x0087, 0xf4d66d54},
+       {0x09ec, 0x008a, 0x06bfa1ff},
+       {0x0902, 0x0015, 0x755025d2},
+       {0x08fe, 0x000e, 0xf690ce2d},
+       {0x00fb, 0x00dc, 0xe55f1528},
+       {0x0eaa, 0x003a, 0x0fe0a8d7},
+       {0x05fb, 0x0006, 0x86281cfb},
+       {0x0dd1, 0x00a7, 0x60ab51b4},
+       {0x0005, 0x001b, 0xf51d969b},
+       {0x077c, 0x00dd, 0xc2fed268},
+       {0x0575, 0x00f5, 0x432c0b1a},
+       {0x05be, 0x0088, 0x78baa04b},
+       {0x0c89, 0x0068, 0xeda9e428},
+       {0x0f5c, 0x0068, 0xec143c76},
+       {0x06a8, 0x0009, 0xd72651ce},
+       {0x060f, 0x008e, 0x765426cd},
+       {0x07b1, 0x0047, 0x2cfcfa0c},
+       {0x04f1, 0x0041, 0x55b172f9},
+       {0x0e05, 0x00ac, 0x61efde93},
+       {0x0bf7, 0x0097, 0x05b83eee},
+       {0x04e9, 0x00f3, 0x9928223a},
+       {0x023a, 0x0005, 0xdfada9bc},
+       {0x0acb, 0x000e, 0x2217cecd},
+       {0x0148, 0x0060, 0xbc3f7405},
+       {0x0764, 0x0059, 0xcbc201b1},
+       {0x021f, 0x0059, 0x5d6b2256},
+       {0x0f1e, 0x006c, 0xdefeeb45},
+       {0x071c, 0x00b9, 0xb9b59309},
+       {0x0564, 0x0063, 0xae064271},
+       {0x0b14, 0x0044, 0xdb867d9b},
+       {0x0e5a, 0x0055, 0xff06b685},
+       {0x015e, 0x00ba, 0x1115ccbc},
+       {0x0379, 0x00e6, 0x5f4e58dd},
+       {0x013b, 0x0067, 0x4897427e},
+       {0x0e64, 0x0071, 0x7af2b7a4},
+       {0x0a11, 0x0050, 0x92105726},
+       {0x0109, 0x0055, 0xd0d000f9},
+       {0x00aa, 0x0022, 0x815d229d},
+       {0x09ac, 0x004f, 0x02f9d985},
+       {0x0e1b, 0x00ce, 0x5cf92ab4},
+       {0x08af, 0x00d8, 0x17ca72d1},
+       {0x0e33, 0x000a, 0xda2dba6b},
+       {0x0ee3, 0x006a, 0xb00048e5},
+       {0x0648, 0x001a, 0x2364b8cb},
+       {0x0315, 0x0085, 0x0596fd0d},
+       {0x0fbb, 0x003e, 0x298230ca},
+       {0x0422, 0x006a, 0x78ada4ab},
+       {0x04ba, 0x0073, 0xced1fbc2},
+       {0x007d, 0x0061, 0x4b7ff236},
+       {0x070b, 0x00d0, 0x261cf0ae},
+       {0x0c1a, 0x0035, 0x8be92ee2},
+       {0x0af8, 0x0063, 0x824dcf03},
+       {0x08f8, 0x006d, 0xd289710c},
+       {0x021b, 0x00ee, 0x6ac1c41d},
+       {0x05b5, 0x00da, 0x8e52f0e2},
+};
+
+int __init
+xfs_dahash_test(void)
+{
+       unsigned int    i;
+       unsigned int    errors = 0;
+
+       for (i = 0; i < ARRAY_SIZE(test); i++) {
+               xfs_dahash_t    hash;
+
+               hash = xfs_da_hashname(test_buf + test[i].start,
+                               test[i].length);
+               if (hash != test[i].dahash)
+                       errors++;
+       }
+
+       if (errors) {
+               printk(KERN_ERR "xfs dir/attr hash test failed %u times!",
+                               errors);
+               return -ERANGE;
+       }
+
+       return 0;
+}
diff --git a/fs/xfs/xfs_dahash_test.h b/fs/xfs/xfs_dahash_test.h
new file mode 100644 (file)
index 0000000..1a05bf4
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_DAHASH_TEST_H__
+#define __XFS_DAHASH_TEST_H__
+
+int xfs_dahash_test(void);
+
+#endif /* __XFS_DAHASH_TEST_H__ */
+
index 69dbe78..285885c 100644 (file)
@@ -1090,9 +1090,12 @@ xfs_buffered_write_iomap_begin(
                 */
                if (xfs_has_allocsize(mp))
                        prealloc_blocks = mp->m_allocsize_blocks;
-               else
+               else if (allocfork == XFS_DATA_FORK)
                        prealloc_blocks = xfs_iomap_prealloc_size(ip, allocfork,
                                                offset, count, &icur);
+               else
+                       prealloc_blocks = xfs_iomap_prealloc_size(ip, allocfork,
+                                               offset, count, &ccur);
                if (prealloc_blocks) {
                        xfs_extlen_t    align;
                        xfs_off_t       end_offset;
index 2479b5c..4f814f9 100644 (file)
@@ -41,6 +41,7 @@
 #include "xfs_attr_item.h"
 #include "xfs_xattr.h"
 #include "xfs_iunlink_item.h"
+#include "xfs_dahash_test.h"
 
 #include <linux/magic.h>
 #include <linux/fs_context.h>
@@ -2286,6 +2287,10 @@ init_xfs_fs(void)
 
        xfs_check_ondisk_structs();
 
+       error = xfs_dahash_test();
+       if (error)
+               return error;
+
        printk(KERN_INFO XFS_VERSION_STRING " with "
                         XFS_BUILD_OPTIONS " enabled\n");
 
index 7dc0fd6..9c0006c 100644 (file)
@@ -1883,6 +1883,13 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed);
 
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_this_ag);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_start_ag);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_first_ag);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_exact_bno);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_near_bno);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_finish);
+
 TRACE_EVENT(xfs_alloc_cur_check,
        TP_PROTO(struct xfs_mount *mp, xfs_btnum_t btnum, xfs_agblock_t bno,
                 xfs_extlen_t len, xfs_extlen_t diff, bool new),
index 738b0e2..617e4f9 100644 (file)
@@ -383,7 +383,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
        struct block_device *bdev = inode->i_sb->s_bdev;
        unsigned int max = bdev_max_zone_append_sectors(bdev);
        struct bio *bio;
-       ssize_t size;
+       ssize_t size = 0;
        int nr_pages;
        ssize_t ret;
 
@@ -426,7 +426,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
                if (bio->bi_iter.bi_sector != wpsector) {
                        zonefs_warn(inode->i_sb,
                                "Corrupted write pointer %llu for zone at %llu\n",
-                               wpsector, z->z_sector);
+                               bio->bi_iter.bi_sector, z->z_sector);
                        ret = -EIO;
                }
        }
index 0a24ab7..8e2eefa 100644 (file)
@@ -9,7 +9,14 @@
 #include <linux/phy.h>
 
 #if IS_ENABLED(CONFIG_ACPI_MDIO)
-int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode);
+int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode,
+                           struct module *owner);
+
+static inline int
+acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *handle)
+{
+       return __acpi_mdiobus_register(mdio, handle, THIS_MODULE);
+}
 #else /* CONFIG_ACPI_MDIO */
 static inline int
 acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
index 220c8c6..f196c19 100644 (file)
@@ -227,6 +227,24 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit);
 extern u64 smccc_has_sve_hint;
 
 /**
+ * arm_smccc_get_soc_id_version()
+ *
+ * Returns the SOC ID version.
+ *
+ * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
+ */
+s32 arm_smccc_get_soc_id_version(void);
+
+/**
+ * arm_smccc_get_soc_id_revision()
+ *
+ * Returns the SOC ID revision.
+ *
+ * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
+ */
+s32 arm_smccc_get_soc_id_revision(void);
+
+/**
  * struct arm_smccc_res - Result from SMC/HVC call
  * @a0-a3 result values from registers 0 to 3
  */
index d4afa85..3a7909e 100644 (file)
@@ -96,6 +96,7 @@ static inline void user_exit_irqoff(void) { }
 static inline int exception_enter(void) { return 0; }
 static inline void exception_exit(enum ctx_state prev_ctx) { }
 static inline int ct_state(void) { return -1; }
+static inline int __ct_state(void) { return -1; }
 static __always_inline bool context_tracking_guest_enter(void) { return false; }
 static inline void context_tracking_guest_exit(void) { }
 #define CT_WARN_ON(cond) do { } while (0)
index 4a4d56f..fdd537e 100644 (file)
@@ -46,7 +46,9 @@ struct context_tracking {
 
 #ifdef CONFIG_CONTEXT_TRACKING
 DECLARE_PER_CPU(struct context_tracking, context_tracking);
+#endif
 
+#ifdef CONFIG_CONTEXT_TRACKING_USER
 static __always_inline int __ct_state(void)
 {
        return arch_atomic_read(this_cpu_ptr(&context_tracking.state)) & CT_STATE_MASK;
index d4901ca..ca736b0 100644 (file)
@@ -351,6 +351,23 @@ unsigned int __pure cpumask_next_wrap(int n, const struct cpumask *mask, int sta
        for_each_andnot_bit(cpu, cpumask_bits(mask1), cpumask_bits(mask2), small_cpumask_bits)
 
 /**
+ * for_each_cpu_or - iterate over every cpu present in either mask
+ * @cpu: the (optionally unsigned) integer iterator
+ * @mask1: the first cpumask pointer
+ * @mask2: the second cpumask pointer
+ *
+ * This saves a temporary CPU mask in many places.  It is equivalent to:
+ *     struct cpumask tmp;
+ *     cpumask_or(&tmp, &mask1, &mask2);
+ *     for_each_cpu(cpu, &tmp)
+ *             ...
+ *
+ * After the loop, cpu is >= nr_cpu_ids.
+ */
+#define for_each_cpu_or(cpu, mask1, mask2)                             \
+       for_each_or_bit(cpu, cpumask_bits(mask1), cpumask_bits(mask2), small_cpumask_bits)
+
+/**
  * cpumask_any_but - return a "random" in a cpumask, but not this one.
  * @mask: the cpumask to search
  * @cpu: the cpu to ignore.
index 04a733f..7aa62c9 100644 (file)
@@ -693,6 +693,7 @@ efi_guid_to_str(efi_guid_t *guid, char *out)
 }
 
 extern void efi_init (void);
+extern void efi_earlycon_reprobe(void);
 #ifdef CONFIG_EFI
 extern void efi_enter_virtual_mode (void);     /* switch EFI to virtual mode, if possible */
 #else
index 4647864..5e4f39e 100644 (file)
@@ -14,6 +14,8 @@ unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigned long
                                        unsigned long nbits, unsigned long start);
 unsigned long _find_next_andnot_bit(const unsigned long *addr1, const unsigned long *addr2,
                                        unsigned long nbits, unsigned long start);
+unsigned long _find_next_or_bit(const unsigned long *addr1, const unsigned long *addr2,
+                                       unsigned long nbits, unsigned long start);
 unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits,
                                         unsigned long start);
 extern unsigned long _find_first_bit(const unsigned long *addr, unsigned long size);
@@ -127,6 +129,36 @@ unsigned long find_next_andnot_bit(const unsigned long *addr1,
 }
 #endif
 
+#ifndef find_next_or_bit
+/**
+ * find_next_or_bit - find the next set bit in either memory regions
+ * @addr1: The first address to base the search on
+ * @addr2: The second address to base the search on
+ * @size: The bitmap size in bits
+ * @offset: The bitnumber to start searching at
+ *
+ * Returns the bit number for the next set bit
+ * If no bits are set, returns @size.
+ */
+static inline
+unsigned long find_next_or_bit(const unsigned long *addr1,
+               const unsigned long *addr2, unsigned long size,
+               unsigned long offset)
+{
+       if (small_const_nbits(size)) {
+               unsigned long val;
+
+               if (unlikely(offset >= size))
+                       return size;
+
+               val = (*addr1 | *addr2) & GENMASK(size - 1, offset);
+               return val ? __ffs(val) : size;
+       }
+
+       return _find_next_or_bit(addr1, addr2, size, offset);
+}
+#endif
+
 #ifndef find_next_zero_bit
 /**
  * find_next_zero_bit - find the next cleared bit in a memory region
@@ -536,6 +568,11 @@ unsigned long find_next_bit_le(const void *addr, unsigned
             (bit) = find_next_andnot_bit((addr1), (addr2), (size), (bit)), (bit) < (size);\
             (bit)++)
 
+#define for_each_or_bit(bit, addr1, addr2, size) \
+       for ((bit) = 0;                                                                 \
+            (bit) = find_next_or_bit((addr1), (addr2), (size), (bit)), (bit) < (size);\
+            (bit)++)
+
 /* same as for_each_set_bit() but use bit as value to start with */
 #define for_each_set_bit_from(bit, addr, size) \
        for (; (bit) = find_next_bit((addr), (size), (bit)), (bit) < (size); (bit)++)
index 934e5dd..35b9328 100644 (file)
@@ -27,7 +27,7 @@ struct io_uring_cmd {
        const void      *cmd;
        union {
                /* callback to defer completions to task context */
-               void (*task_work_cb)(struct io_uring_cmd *cmd);
+               void (*task_work_cb)(struct io_uring_cmd *cmd, unsigned);
                /* used for polled completion */
                void *cookie;
        };
@@ -39,9 +39,10 @@ struct io_uring_cmd {
 #if defined(CONFIG_IO_URING)
 int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
                              struct iov_iter *iter, void *ioucmd);
-void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2);
+void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2,
+                       unsigned issue_flags);
 void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
-                       void (*task_work_cb)(struct io_uring_cmd *));
+                       void (*task_work_cb)(struct io_uring_cmd *, unsigned));
 struct sock *io_uring_get_socket(struct file *file);
 void __io_uring_cancel(bool cancel_all);
 void __io_uring_free(struct task_struct *tsk);
@@ -72,11 +73,11 @@ static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
        return -EOPNOTSUPP;
 }
 static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret,
-               ssize_t ret2)
+               ssize_t ret2, unsigned issue_flags)
 {
 }
 static inline void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
-                       void (*task_work_cb)(struct io_uring_cmd *))
+                       void (*task_work_cb)(struct io_uring_cmd *, unsigned))
 {
 }
 static inline struct sock *io_uring_get_socket(struct file *file)
index 5686711..2223f95 100644 (file)
@@ -151,12 +151,6 @@ int gic_of_init(struct device_node *node, struct device_node *parent);
  */
 int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq);
 
-/*
- * Legacy platforms not converted to DT yet must use this to init
- * their GIC
- */
-void gic_init(void __iomem *dist , void __iomem *cpu);
-
 void gic_send_sgi(unsigned int cpu_id, unsigned int irq);
 int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
index 9a6b55d..72831e3 100644 (file)
@@ -22,6 +22,7 @@
 #define        nlm4_fbig               cpu_to_be32(NLM_FBIG)
 #define        nlm4_failed             cpu_to_be32(NLM_FAILED)
 
+void   nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len);
 bool   nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool   nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool   nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
index 7547015..57ebe12 100644 (file)
@@ -115,8 +115,9 @@ struct nvme_tcp_icresp_pdu {
 struct nvme_tcp_term_pdu {
        struct nvme_tcp_hdr     hdr;
        __le16                  fes;
-       __le32                  fei;
-       __u8                    rsvd[8];
+       __le16                  feil;
+       __le16                  feiu;
+       __u8                    rsvd[10];
 };
 
 /**
index da633d3..8a52ef2 100644 (file)
 
 #if IS_ENABLED(CONFIG_OF_MDIO)
 bool of_mdiobus_child_is_phy(struct device_node *child);
-int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
-int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
-                            struct device_node *np);
+int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
+                         struct module *owner);
+
+static inline int of_mdiobus_register(struct mii_bus *mdio,
+                                     struct device_node *np)
+{
+       return __of_mdiobus_register(mdio, np, THIS_MODULE);
+}
+
+int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
+                              struct device_node *np, struct module *owner);
+
+static inline int devm_of_mdiobus_register(struct device *dev,
+                                          struct mii_bus *mdio,
+                                          struct device_node *np)
+{
+       return __devm_of_mdiobus_register(dev, mdio, np, THIS_MODULE);
+}
+
 struct mdio_device *of_mdio_find_device(struct device_node *np);
 struct phy_device *of_phy_find_device(struct device_node *phy_np);
 struct phy_device *
index 521a733..75b73c8 100644 (file)
@@ -45,7 +45,6 @@ void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
 void percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount,
                              s32 batch);
 s64 __percpu_counter_sum(struct percpu_counter *fbc);
-s64 percpu_counter_sum_all(struct percpu_counter *fbc);
 int __percpu_counter_compare(struct percpu_counter *fbc, s64 rhs, s32 batch);
 void percpu_counter_sync(struct percpu_counter *fbc);
 
@@ -196,11 +195,6 @@ static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
        return percpu_counter_read(fbc);
 }
 
-static inline s64 percpu_counter_sum_all(struct percpu_counter *fbc)
-{
-       return percpu_counter_read(fbc);
-}
-
 static inline bool percpu_counter_initialized(struct percpu_counter *fbc)
 {
        return true;
index a152678..a2414c1 100644 (file)
@@ -215,7 +215,7 @@ struct plat_stmmacenet_data {
        int unicast_filter_entries;
        int tx_fifo_size;
        int rx_fifo_size;
-       u32 addr64;
+       u32 host_dma_width;
        u32 rx_queues_to_use;
        u32 tx_queues_to_use;
        u8 rx_sched_algorithm;
index 8ba8b5b..c1ef5fc 100644 (file)
@@ -70,11 +70,16 @@ static inline void sysfb_disable(void)
 #ifdef CONFIG_EFI
 
 extern struct efifb_dmi_info efifb_dmi_list[];
-void sysfb_apply_efi_quirks(struct platform_device *pd);
+void sysfb_apply_efi_quirks(void);
+void sysfb_set_efifb_fwnode(struct platform_device *pd);
 
 #else /* CONFIG_EFI */
 
-static inline void sysfb_apply_efi_quirks(struct platform_device *pd)
+static inline void sysfb_apply_efi_quirks(void)
+{
+}
+
+static inline void sysfb_set_efifb_fwnode(struct platform_device *pd)
 {
 }
 
index 2bb4bf3..13c6aae 100644 (file)
@@ -384,6 +384,7 @@ devm_thermal_of_cooling_device_register(struct device *dev,
                                struct device_node *np,
                                char *type, void *devdata,
                                const struct thermal_cooling_device_ops *ops);
+void thermal_cooling_device_update(struct thermal_cooling_device *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
index 7254edf..6ed9b4d 100644 (file)
@@ -1613,6 +1613,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn);
 void hci_conn_del_sysfs(struct hci_conn *conn);
 
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
+#define GET_HCIDEV_DEV(hdev) ((hdev)->dev.parent)
 
 /* ----- LMP capabilities ----- */
 #define lmp_encrypt_capable(dev)   ((dev)->features[0][0] & LMP_ENCRYPT)
index 216de5f..f8d6148 100644 (file)
@@ -35,7 +35,7 @@ TRACE_EVENT(vm_unmapped_area,
                __entry->align_offset = info->align_offset;
        ),
 
-       TP_printk("addr=0x%lx err=%ld total_vm=0x%lx flags=0x%lx len=0x%lx lo=0x%lx hi=0x%lx mask=0x%lx ofs=0x%lx\n",
+       TP_printk("addr=0x%lx err=%ld total_vm=0x%lx flags=0x%lx len=0x%lx lo=0x%lx hi=0x%lx mask=0x%lx ofs=0x%lx",
                IS_ERR_VALUE(__entry->addr) ? 0 : __entry->addr,
                IS_ERR_VALUE(__entry->addr) ? __entry->addr : 0,
                __entry->total_vm, __entry->flags, __entry->length,
@@ -110,7 +110,7 @@ TRACE_EVENT(exit_mmap,
                       __entry->mt              = &mm->mm_mt;
        ),
 
-       TP_printk("mt_mod %p, DESTROY\n",
+       TP_printk("mt_mod %p, DESTROY",
                  __entry->mt
        )
 );
index 4425d17..bb87b78 100644 (file)
@@ -156,7 +156,7 @@ static char *extra_init_args;
 
 #ifdef CONFIG_BOOT_CONFIG
 /* Is bootconfig on command line? */
-static bool bootconfig_found = IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE);
+static bool bootconfig_found;
 static size_t initargs_offs;
 #else
 # define bootconfig_found false
@@ -429,7 +429,7 @@ static void __init setup_boot_config(void)
        err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
                         bootconfig_params);
 
-       if (IS_ERR(err) || !bootconfig_found)
+       if (IS_ERR(err) || !(bootconfig_found || IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE)))
                return;
 
        /* parse_args() stops at the next param of '--' and returns an address */
@@ -437,7 +437,11 @@ static void __init setup_boot_config(void)
                initargs_offs = err - tmp_cmdline;
 
        if (!data) {
-               pr_err("'bootconfig' found on command line, but no bootconfig found\n");
+               /* If user intended to use bootconfig, show an error level message */
+               if (bootconfig_found)
+                       pr_err("'bootconfig' found on command line, but no bootconfig found\n");
+               else
+                       pr_info("No bootconfig data provided, so skipping bootconfig");
                return;
        }
 
index 68dfc69..b80614e 100644 (file)
@@ -19,6 +19,9 @@ static int io_file_bitmap_get(struct io_ring_ctx *ctx)
        unsigned long nr = ctx->file_alloc_end;
        int ret;
 
+       if (!table->bitmap)
+               return -ENFILE;
+
        do {
                ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint);
                if (ret != nr)
index b7f190c..4040cf0 100644 (file)
@@ -47,6 +47,7 @@ struct io_connect {
        struct sockaddr __user          *addr;
        int                             addr_len;
        bool                            in_progress;
+       bool                            seen_econnaborted;
 };
 
 struct io_sr_msg {
@@ -1424,7 +1425,7 @@ int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
        conn->addr_len =  READ_ONCE(sqe->addr2);
-       conn->in_progress = false;
+       conn->in_progress = conn->seen_econnaborted = false;
        return 0;
 }
 
@@ -1461,18 +1462,24 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 
        ret = __sys_connect_file(req->file, &io->address,
                                        connect->addr_len, file_flags);
-       if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
+       if ((ret == -EAGAIN || ret == -EINPROGRESS || ret == -ECONNABORTED)
+           && force_nonblock) {
                if (ret == -EINPROGRESS) {
                        connect->in_progress = true;
-               } else {
-                       if (req_has_async_data(req))
-                               return -EAGAIN;
-                       if (io_alloc_async_data(req)) {
-                               ret = -ENOMEM;
+                       return -EAGAIN;
+               }
+               if (ret == -ECONNABORTED) {
+                       if (connect->seen_econnaborted)
                                goto out;
-                       }
-                       memcpy(req->async_data, &__io, sizeof(__io));
+                       connect->seen_econnaborted = true;
+               }
+               if (req_has_async_data(req))
+                       return -EAGAIN;
+               if (io_alloc_async_data(req)) {
+                       ret = -ENOMEM;
+                       goto out;
                }
+               memcpy(req->async_data, &__io, sizeof(__io));
                return -EAGAIN;
        }
        if (ret == -ERESTARTSYS)
index e2bac9f..7a43aed 100644 (file)
@@ -794,6 +794,7 @@ void __io_sqe_files_unregister(struct io_ring_ctx *ctx)
        }
 #endif
        io_free_file_tables(&ctx->file_table);
+       io_file_table_set_alloc_range(ctx, 0, 0);
        io_rsrc_data_free(ctx->file_data);
        ctx->file_data = NULL;
        ctx->nr_user_files = 0;
index 2e4c483..9a1dee5 100644 (file)
 static void io_uring_cmd_work(struct io_kiocb *req, bool *locked)
 {
        struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
+       unsigned issue_flags = *locked ? 0 : IO_URING_F_UNLOCKED;
 
-       ioucmd->task_work_cb(ioucmd);
+       ioucmd->task_work_cb(ioucmd, issue_flags);
 }
 
 void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
-                       void (*task_work_cb)(struct io_uring_cmd *))
+                       void (*task_work_cb)(struct io_uring_cmd *, unsigned))
 {
        struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
 
@@ -42,7 +43,8 @@ static inline void io_req_set_cqe32_extra(struct io_kiocb *req,
  * Called by consumers of io_uring_cmd, if they originally returned
  * -EIOCBQUEUED upon receiving the command.
  */
-void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2)
+void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2,
+                      unsigned issue_flags)
 {
        struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
 
@@ -56,7 +58,7 @@ void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2)
                /* order with io_iopoll_req_issued() checking ->iopoll_complete */
                smp_store_release(&req->iopoll_completed, 1);
        else
-               io_req_complete_post(req, 0);
+               io_req_complete_post(req, issue_flags);
 }
 EXPORT_SYMBOL_GPL(io_uring_cmd_done);
 
index b297e9f..e2d256c 100644 (file)
@@ -972,7 +972,7 @@ static int __init bpf_jit_charge_init(void)
 {
        /* Only used as heuristic here to derive limit. */
        bpf_jit_limit_max = bpf_jit_alloc_exec_limit();
-       bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2,
+       bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 1,
                                            PAGE_SIZE), LONG_MAX);
        return 0;
 }
index 272563a..d517d13 100644 (file)
@@ -3826,6 +3826,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
                                                continue;
                                        if (type == STACK_MISC)
                                                continue;
+                                       if (type == STACK_INVALID && env->allow_uninit_stack)
+                                               continue;
                                        verbose(env, "invalid read from stack off %d+%d size %d\n",
                                                off, i, size);
                                        return -EACCES;
@@ -3863,6 +3865,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
                                continue;
                        if (type == STACK_ZERO)
                                continue;
+                       if (type == STACK_INVALID && env->allow_uninit_stack)
+                               continue;
                        verbose(env, "invalid read from stack off %d+%d size %d\n",
                                off, i, size);
                        return -EACCES;
@@ -5754,7 +5758,8 @@ static int check_stack_range_initialized(
                stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE];
                if (*stype == STACK_MISC)
                        goto mark;
-               if (*stype == STACK_ZERO) {
+               if ((*stype == STACK_ZERO) ||
+                   (*stype == STACK_INVALID && env->allow_uninit_stack)) {
                        if (clobber) {
                                /* helper can write anything into the stack */
                                *stype = STACK_MISC;
@@ -13936,6 +13941,10 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
                if (old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_INVALID)
                        continue;
 
+               if (env->allow_uninit_stack &&
+                   old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_MISC)
+                       continue;
+
                /* explored stack has more populated slots than current stack
                 * and these slots were used
                 */
index 846add8..be61332 100644 (file)
@@ -21,7 +21,7 @@ static __always_inline void __enter_from_user_mode(struct pt_regs *regs)
        arch_enter_from_user_mode(regs);
        lockdep_hardirqs_off(CALLER_ADDR0);
 
-       CT_WARN_ON(ct_state() != CONTEXT_USER);
+       CT_WARN_ON(__ct_state() != CONTEXT_USER);
        user_exit_irqoff();
 
        instrumentation_begin();
@@ -192,13 +192,14 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
 
 static void exit_to_user_mode_prepare(struct pt_regs *regs)
 {
-       unsigned long ti_work = read_thread_flags();
+       unsigned long ti_work;
 
        lockdep_assert_irqs_disabled();
 
        /* Flush pending rcuog wakeup before the last need_resched() check */
        tick_nohz_user_enter_prepare();
 
+       ti_work = read_thread_flags();
        if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
                ti_work = exit_to_user_mode_loop(regs, ti_work);
 
index d8cda4c..c0257cb 100644 (file)
@@ -755,11 +755,6 @@ static void check_mm(struct mm_struct *mm)
        for (i = 0; i < NR_MM_COUNTERS; i++) {
                long x = percpu_counter_sum(&mm->rss_stat[i]);
 
-               if (likely(!x))
-                       continue;
-
-               /* Making sure this is not due to race with CPU offlining. */
-               x = percpu_counter_sum_all(&mm->rss_stat[i]);
                if (unlikely(x))
                        pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n",
                                 mm, resident_page_types[i], x);
index 8cf70f0..a45f3df 100644 (file)
@@ -16,6 +16,6 @@ obj-y := core.o debugfs.o report.o
 KCSAN_INSTRUMENT_BARRIERS_selftest.o := y
 obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o
 
-CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer
+CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -fno-omit-frame-pointer
 CFLAGS_kcsan_test.o += $(DISABLE_STRUCTLEAK_PLUGIN)
 obj-$(CONFIG_KCSAN_KUNIT_TEST) += kcsan_test.o
index 488655f..0d18c39 100644 (file)
@@ -2084,6 +2084,9 @@ static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
 
 void activate_task(struct rq *rq, struct task_struct *p, int flags)
 {
+       if (task_on_rq_migrating(p))
+               flags |= ENQUEUE_MIGRATED;
+
        enqueue_task(rq, p, flags);
 
        p->on_rq = TASK_ON_RQ_QUEUED;
index 7a1b1f8..6986ea3 100644 (file)
@@ -4648,11 +4648,33 @@ static void check_spread(struct cfs_rq *cfs_rq, struct sched_entity *se)
 #endif
 }
 
+static inline bool entity_is_long_sleeper(struct sched_entity *se)
+{
+       struct cfs_rq *cfs_rq;
+       u64 sleep_time;
+
+       if (se->exec_start == 0)
+               return false;
+
+       cfs_rq = cfs_rq_of(se);
+
+       sleep_time = rq_clock_task(rq_of(cfs_rq));
+
+       /* Happen while migrating because of clock task divergence */
+       if (sleep_time <= se->exec_start)
+               return false;
+
+       sleep_time -= se->exec_start;
+       if (sleep_time > ((1ULL << 63) / scale_load_down(NICE_0_LOAD)))
+               return true;
+
+       return false;
+}
+
 static void
 place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
 {
        u64 vruntime = cfs_rq->min_vruntime;
-       u64 sleep_time;
 
        /*
         * The 'current' period is already promised to the current tasks,
@@ -4684,13 +4706,24 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
 
        /*
         * Pull vruntime of the entity being placed to the base level of
-        * cfs_rq, to prevent boosting it if placed backwards.  If the entity
-        * slept for a long time, don't even try to compare its vruntime with
-        * the base as it may be too far off and the comparison may get
-        * inversed due to s64 overflow.
-        */
-       sleep_time = rq_clock_task(rq_of(cfs_rq)) - se->exec_start;
-       if ((s64)sleep_time > 60LL * NSEC_PER_SEC)
+        * cfs_rq, to prevent boosting it if placed backwards.
+        * However, min_vruntime can advance much faster than real time, with
+        * the extreme being when an entity with the minimal weight always runs
+        * on the cfs_rq. If the waking entity slept for a long time, its
+        * vruntime difference from min_vruntime may overflow s64 and their
+        * comparison may get inversed, so ignore the entity's original
+        * vruntime in that case.
+        * The maximal vruntime speedup is given by the ratio of normal to
+        * minimal weight: scale_load_down(NICE_0_LOAD) / MIN_SHARES.
+        * When placing a migrated waking entity, its exec_start has been set
+        * from a different rq. In order to take into account a possible
+        * divergence between new and prev rq's clocks task because of irq and
+        * stolen time, we take an additional margin.
+        * So, cutting off on the sleep time of
+        *     2^63 / scale_load_down(NICE_0_LOAD) ~ 104 days
+        * should be safe.
+        */
+       if (entity_is_long_sleeper(se))
                se->vruntime = vruntime;
        else
                se->vruntime = max_vruntime(se->vruntime, vruntime);
@@ -4770,6 +4803,9 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 
        if (flags & ENQUEUE_WAKEUP)
                place_entity(cfs_rq, se, 0);
+       /* Entity has migrated, no longer consider this task hot */
+       if (flags & ENQUEUE_MIGRATED)
+               se->exec_start = 0;
 
        check_schedstat_required();
        update_stats_enqueue_fair(cfs_rq, se, flags);
@@ -7657,9 +7693,6 @@ static void migrate_task_rq_fair(struct task_struct *p, int new_cpu)
        /* Tell new CPU we are migrated */
        se->avg.last_update_time = 0;
 
-       /* We have migrated, no longer consider this task hot */
-       se->exec_start = 0;
-
        update_scan_period(p, new_cpu);
 }
 
index f9d33ef..f15ac66 100644 (file)
@@ -31,6 +31,7 @@ MODULE_PARM_DESC(iterations,
 
 static void dhry_benchmark(void)
 {
+       unsigned int cpu = get_cpu();
        int i, n;
 
        if (iterations > 0) {
@@ -45,9 +46,10 @@ static void dhry_benchmark(void)
        }
 
 report:
+       put_cpu();
        if (n >= 0)
-               pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n",
-                       smp_processor_id(), n, n / DHRY_VAX);
+               pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n", cpu,
+                       n, n / DHRY_VAX);
        else if (n == -EAGAIN)
                pr_err("Please increase the number of iterations\n");
        else
index c10920e..32f99e9 100644 (file)
@@ -182,6 +182,15 @@ unsigned long _find_next_andnot_bit(const unsigned long *addr1, const unsigned l
 EXPORT_SYMBOL(_find_next_andnot_bit);
 #endif
 
+#ifndef find_next_or_bit
+unsigned long _find_next_or_bit(const unsigned long *addr1, const unsigned long *addr2,
+                                       unsigned long nbits, unsigned long start)
+{
+       return FIND_NEXT_BIT(addr1[idx] | addr2[idx], /* nop */, nbits, start);
+}
+EXPORT_SYMBOL(_find_next_or_bit);
+#endif
+
 #ifndef find_next_zero_bit
 unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits,
                                         unsigned long start)
index 646297c..9e2735c 100644 (file)
@@ -5099,35 +5099,21 @@ static inline bool mas_rewind_node(struct ma_state *mas)
  */
 static inline bool mas_skip_node(struct ma_state *mas)
 {
-       unsigned char slot, slot_count;
-       unsigned long *pivots;
-       enum maple_type mt;
+       if (mas_is_err(mas))
+               return false;
 
-       mt = mte_node_type(mas->node);
-       slot_count = mt_slots[mt] - 1;
        do {
                if (mte_is_root(mas->node)) {
-                       slot = mas->offset;
-                       if (slot > slot_count) {
+                       if (mas->offset >= mas_data_end(mas)) {
                                mas_set_err(mas, -EBUSY);
                                return false;
                        }
                } else {
                        mas_ascend(mas);
-                       slot = mas->offset;
-                       mt = mte_node_type(mas->node);
-                       slot_count = mt_slots[mt] - 1;
                }
-       } while (slot > slot_count);
-
-       mas->offset = ++slot;
-       pivots = ma_pivots(mas_mn(mas), mt);
-       if (slot > 0)
-               mas->min = pivots[slot - 1] + 1;
-
-       if (slot <= slot_count)
-               mas->max = pivots[slot];
+       } while (mas->offset >= mas_data_end(mas));
 
+       mas->offset++;
        return true;
 }
 
index dba56c5..5004463 100644 (file)
@@ -122,8 +122,19 @@ void percpu_counter_sync(struct percpu_counter *fbc)
 }
 EXPORT_SYMBOL(percpu_counter_sync);
 
-static s64 __percpu_counter_sum_mask(struct percpu_counter *fbc,
-                             const struct cpumask *cpu_mask)
+/*
+ * Add up all the per-cpu counts, return the result.  This is a more accurate
+ * but much slower version of percpu_counter_read_positive().
+ *
+ * We use the cpu mask of (cpu_online_mask | cpu_dying_mask) to capture sums
+ * from CPUs that are in the process of being taken offline. Dying cpus have
+ * been removed from the online mask, but may not have had the hotplug dead
+ * notifier called to fold the percpu count back into the global counter sum.
+ * By including dying CPUs in the iteration mask, we avoid this race condition
+ * so __percpu_counter_sum() just does the right thing when CPUs are being taken
+ * offline.
+ */
+s64 __percpu_counter_sum(struct percpu_counter *fbc)
 {
        s64 ret;
        int cpu;
@@ -131,35 +142,15 @@ static s64 __percpu_counter_sum_mask(struct percpu_counter *fbc,
 
        raw_spin_lock_irqsave(&fbc->lock, flags);
        ret = fbc->count;
-       for_each_cpu(cpu, cpu_mask) {
+       for_each_cpu_or(cpu, cpu_online_mask, cpu_dying_mask) {
                s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
                ret += *pcount;
        }
        raw_spin_unlock_irqrestore(&fbc->lock, flags);
        return ret;
 }
-
-/*
- * Add up all the per-cpu counts, return the result.  This is a more accurate
- * but much slower version of percpu_counter_read_positive()
- */
-s64 __percpu_counter_sum(struct percpu_counter *fbc)
-{
-       return __percpu_counter_sum_mask(fbc, cpu_online_mask);
-}
 EXPORT_SYMBOL(__percpu_counter_sum);
 
-/*
- * This is slower version of percpu_counter_sum as it traverses all possible
- * cpus. Use this only in the cases where accurate data is needed in the
- * presense of CPUs getting offlined.
- */
-s64 percpu_counter_sum_all(struct percpu_counter *fbc)
-{
-       return __percpu_counter_sum_mask(fbc, cpu_possible_mask);
-}
-EXPORT_SYMBOL(percpu_counter_sum_all);
-
 int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, gfp_t gfp,
                          struct lock_class_key *key)
 {
index 3d19b1f..f1db333 100644 (file)
@@ -2670,6 +2670,49 @@ static noinline void check_empty_area_window(struct maple_tree *mt)
        rcu_read_unlock();
 }
 
+static noinline void check_empty_area_fill(struct maple_tree *mt)
+{
+       const unsigned long max = 0x25D78000;
+       unsigned long size;
+       int loop, shift;
+       MA_STATE(mas, mt, 0, 0);
+
+       mt_set_non_kernel(99999);
+       for (shift = 12; shift <= 16; shift++) {
+               loop = 5000;
+               size = 1 << shift;
+               while (loop--) {
+                       mas_set(&mas, 0);
+                       mas_lock(&mas);
+                       MT_BUG_ON(mt, mas_empty_area(&mas, 0, max, size) != 0);
+                       MT_BUG_ON(mt, mas.last != mas.index + size - 1);
+                       mas_store_gfp(&mas, (void *)size, GFP_KERNEL);
+                       mas_unlock(&mas);
+                       mas_reset(&mas);
+               }
+       }
+
+       /* No space left. */
+       size = 0x1000;
+       rcu_read_lock();
+       MT_BUG_ON(mt, mas_empty_area(&mas, 0, max, size) != -EBUSY);
+       rcu_read_unlock();
+
+       /* Fill a depth 3 node to the maximum */
+       for (unsigned long i = 629440511; i <= 629440800; i += 6)
+               mtree_store_range(mt, i, i + 5, (void *)i, GFP_KERNEL);
+       /* Make space in the second-last depth 4 node */
+       mtree_erase(mt, 631668735);
+       /* Make space in the last depth 4 node */
+       mtree_erase(mt, 629506047);
+       mas_reset(&mas);
+       /* Search from just after the gap in the second-last depth 4 */
+       rcu_read_lock();
+       MT_BUG_ON(mt, mas_empty_area(&mas, 629506048, 690000000, 0x5000) != 0);
+       rcu_read_unlock();
+       mt_set_non_kernel(0);
+}
+
 static DEFINE_MTREE(tree);
 static int maple_tree_seed(void)
 {
@@ -2926,6 +2969,11 @@ static int maple_tree_seed(void)
        check_empty_area_window(&tree);
        mtree_destroy(&tree);
 
+       mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
+       check_empty_area_fill(&tree);
+       mtree_destroy(&tree);
+
+
 #if defined(BENCH)
 skip:
 #endif
index 0bb9572..2de2a58 100644 (file)
@@ -2,5 +2,5 @@
 
 obj-y := core.o report.o
 
-CFLAGS_kfence_test.o := -g -fno-omit-frame-pointer -fno-optimize-sibling-calls
+CFLAGS_kfence_test.o := -fno-omit-frame-pointer -fno-optimize-sibling-calls
 obj-$(CONFIG_KFENCE_KUNIT_TEST) += kfence_test.o
index 5349c37..79c94ee 100644 (file)
@@ -726,10 +726,14 @@ static const struct seq_operations objects_sops = {
 };
 DEFINE_SEQ_ATTRIBUTE(objects);
 
-static int __init kfence_debugfs_init(void)
+static int kfence_debugfs_init(void)
 {
-       struct dentry *kfence_dir = debugfs_create_dir("kfence", NULL);
+       struct dentry *kfence_dir;
 
+       if (!READ_ONCE(kfence_enabled))
+               return 0;
+
+       kfence_dir = debugfs_create_dir("kfence", NULL);
        debugfs_create_file("stats", 0444, kfence_dir, NULL, &stats_fops);
        debugfs_create_file("objects", 0400, kfence_dir, NULL, &objects_fops);
        return 0;
@@ -883,6 +887,8 @@ static int kfence_init_late(void)
        }
 
        kfence_init_enable();
+       kfence_debugfs_init();
+
        return 0;
 }
 
index ad591b7..2b8d300 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -988,9 +988,15 @@ static int unmerge_and_remove_all_rmap_items(void)
 
                mm = mm_slot->slot.mm;
                mmap_read_lock(mm);
+
+               /*
+                * Exit right away if mm is exiting to avoid lockdep issue in
+                * the maple tree
+                */
+               if (ksm_test_exit(mm))
+                       goto mm_exiting;
+
                for_each_vma(vmi, vma) {
-                       if (ksm_test_exit(mm))
-                               break;
                        if (!(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma)
                                continue;
                        err = unmerge_ksm_pages(vma,
@@ -999,6 +1005,7 @@ static int unmerge_and_remove_all_rmap_items(void)
                                goto error;
                }
 
+mm_exiting:
                remove_trailing_rmap_items(&mm_slot->rmap_list);
                mmap_read_unlock(mm);
 
index 740b54b..ad499f7 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2621,12 +2621,7 @@ cannot_expand:
 
        if (map_deny_write_exec(vma, vma->vm_flags)) {
                error = -EACCES;
-               if (file)
-                       goto close_and_free_vma;
-               else if (vma->vm_file)
-                       goto unmap_and_free_vma;
-               else
-                       goto free_vma;
+               goto close_and_free_vma;
        }
 
        /* Allow architectures to sanity-check the vm_flags */
index 231929f..13e84d8 100644 (file)
@@ -805,7 +805,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
 
                if (map_deny_write_exec(vma, newflags)) {
                        error = -EACCES;
-                       goto out;
+                       break;
                }
 
                /* Allow architectures to sanity-check the new flags */
index ac1fc98..7136c36 100644 (file)
@@ -1398,6 +1398,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
                        unsigned int order, bool check_free, fpi_t fpi_flags)
 {
        int bad = 0;
+       bool skip_kasan_poison = should_skip_kasan_poison(page, fpi_flags);
        bool init = want_init_on_free();
 
        VM_BUG_ON_PAGE(PageTail(page), page);
@@ -1470,7 +1471,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
         * With hardware tag-based KASAN, memory tags must be set before the
         * page becomes unavailable via debug_pagealloc or arch_free_page.
         */
-       if (!should_skip_kasan_poison(page, fpi_flags)) {
+       if (!skip_kasan_poison) {
                kasan_poison_pages(page, order, init);
 
                /* Memory is already initialized if KASAN did it internally. */
index dabc2a6..edbe722 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -839,7 +839,7 @@ static int init_cache_node(struct kmem_cache *cachep, int node, gfp_t gfp)
        return 0;
 }
 
-#if (defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)) || defined(CONFIG_SMP)
+#if defined(CONFIG_NUMA) || defined(CONFIG_SMP)
 /*
  * Allocates and initializes node for a node on each slab cache, used for
  * either memory or cpu hotplug.  If memory is being hot-added, the kmem_cache_node
index ef910bf..bef6cf2 100644 (file)
@@ -2883,6 +2883,8 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
                unsigned int order, unsigned int nr_pages, struct page **pages)
 {
        unsigned int nr_allocated = 0;
+       gfp_t alloc_gfp = gfp;
+       bool nofail = false;
        struct page *page;
        int i;
 
@@ -2893,6 +2895,7 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
         * more permissive.
         */
        if (!order) {
+               /* bulk allocator doesn't support nofail req. officially */
                gfp_t bulk_gfp = gfp & ~__GFP_NOFAIL;
 
                while (nr_allocated < nr_pages) {
@@ -2931,20 +2934,35 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
                        if (nr != nr_pages_request)
                                break;
                }
+       } else if (gfp & __GFP_NOFAIL) {
+               /*
+                * Higher order nofail allocations are really expensive and
+                * potentially dangerous (pre-mature OOM, disruptive reclaim
+                * and compaction etc.
+                */
+               alloc_gfp &= ~__GFP_NOFAIL;
+               nofail = true;
        }
 
        /* High-order pages or fallback path if "bulk" fails. */
-
        while (nr_allocated < nr_pages) {
                if (fatal_signal_pending(current))
                        break;
 
                if (nid == NUMA_NO_NODE)
-                       page = alloc_pages(gfp, order);
+                       page = alloc_pages(alloc_gfp, order);
                else
-                       page = alloc_pages_node(nid, gfp, order);
-               if (unlikely(!page))
-                       break;
+                       page = alloc_pages_node(nid, alloc_gfp, order);
+               if (unlikely(!page)) {
+                       if (!nofail)
+                               break;
+
+                       /* fall back to the zero order allocations */
+                       alloc_gfp |= __GFP_NOFAIL;
+                       order = 0;
+                       continue;
+               }
+
                /*
                 * Higher order allocations must be able to be treated as
                 * indepdenent small pages by callers (as they can with
index b65c3aa..334e308 100644 (file)
@@ -2871,10 +2871,25 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
                return -ENXIO;
        }
 
-       if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
-           hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
-           hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
-           hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
+       switch (hci_skb_pkt_type(skb)) {
+       case HCI_EVENT_PKT:
+               break;
+       case HCI_ACLDATA_PKT:
+               /* Detect if ISO packet has been sent as ACL */
+               if (hci_conn_num(hdev, ISO_LINK)) {
+                       __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
+                       __u8 type;
+
+                       type = hci_conn_lookup_type(hdev, hci_handle(handle));
+                       if (type == ISO_LINK)
+                               hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
+               }
+               break;
+       case HCI_SCODATA_PKT:
+               break;
+       case HCI_ISODATA_PKT:
+               break;
+       default:
                kfree_skb(skb);
                return -EINVAL;
        }
index 117eedb..5a6aa16 100644 (file)
@@ -643,6 +643,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
        cancel_work_sync(&hdev->cmd_sync_work);
        cancel_work_sync(&hdev->reenable_adv_work);
 
+       mutex_lock(&hdev->cmd_sync_work_lock);
        list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
                if (entry->destroy)
                        entry->destroy(hdev, entry->data, -ECANCELED);
@@ -650,6 +651,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
                list_del(&entry->list);
                kfree(entry);
        }
+       mutex_unlock(&hdev->cmd_sync_work_lock);
 }
 
 void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
@@ -2367,6 +2369,45 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
        return err;
 }
 
+static int hci_pause_addr_resolution(struct hci_dev *hdev)
+{
+       int err;
+
+       if (!use_ll_privacy(hdev))
+               return 0;
+
+       if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION))
+               return 0;
+
+       /* Cannot disable addr resolution if scanning is enabled or
+        * when initiating an LE connection.
+        */
+       if (hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
+           hci_lookup_le_connect(hdev)) {
+               bt_dev_err(hdev, "Command not allowed when scan/LE connect");
+               return -EPERM;
+       }
+
+       /* Cannot disable addr resolution if advertising is enabled. */
+       err = hci_pause_advertising_sync(hdev);
+       if (err) {
+               bt_dev_err(hdev, "Pause advertising failed: %d", err);
+               return err;
+       }
+
+       err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
+       if (err)
+               bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
+                          err);
+
+       /* Return if address resolution is disabled and RPA is not used. */
+       if (!err && scan_use_rpa(hdev))
+               return err;
+
+       hci_resume_advertising_sync(hdev);
+       return err;
+}
+
 struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
                                             bool extended, struct sock *sk)
 {
@@ -2402,7 +2443,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
        u8 filter_policy;
        int err;
 
-       /* Pause advertising if resolving list can be used as controllers are
+       /* Pause advertising if resolving list can be used as controllers
         * cannot accept resolving list modifications while advertising.
         */
        if (use_ll_privacy(hdev)) {
@@ -3319,6 +3360,7 @@ static const struct hci_init_stage amp_init1[] = {
        HCI_INIT(hci_read_flow_control_mode_sync),
        /* HCI_OP_READ_LOCATION_DATA */
        HCI_INIT(hci_read_location_data_sync),
+       {}
 };
 
 static int hci_init1_sync(struct hci_dev *hdev)
@@ -3353,6 +3395,7 @@ static int hci_init1_sync(struct hci_dev *hdev)
 static const struct hci_init_stage amp_init2[] = {
        /* HCI_OP_READ_LOCAL_FEATURES */
        HCI_INIT(hci_read_local_features_sync),
+       {}
 };
 
 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
@@ -5394,27 +5437,12 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
 
        cancel_interleave_scan(hdev);
 
-       /* Pause advertising since active scanning disables address resolution
-        * which advertising depend on in order to generate its RPAs.
-        */
-       if (use_ll_privacy(hdev) && hci_dev_test_flag(hdev, HCI_PRIVACY)) {
-               err = hci_pause_advertising_sync(hdev);
-               if (err) {
-                       bt_dev_err(hdev, "pause advertising failed: %d", err);
-                       goto failed;
-               }
-       }
-
-       /* Disable address resolution while doing active scanning since the
-        * accept list shall not be used and all reports shall reach the host
-        * anyway.
+       /* Pause address resolution for active scan and stop advertising if
+        * privacy is enabled.
         */
-       err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
-       if (err) {
-               bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
-                          err);
+       err = hci_pause_addr_resolution(hdev);
+       if (err)
                goto failed;
-       }
 
        /* All active scans will be done with either a resolvable private
         * address (when privacy feature has been enabled) or non-resolvable
index 24444b5..8d136a7 100644 (file)
@@ -1620,7 +1620,6 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
        struct iso_conn *conn = hcon->iso_data;
-       struct hci_iso_data_hdr *hdr;
        __u16 pb, ts, len;
 
        if (!conn)
@@ -1642,6 +1641,8 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                }
 
                if (ts) {
+                       struct hci_iso_ts_data_hdr *hdr;
+
                        /* TODO: add timestamp to the packet? */
                        hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
                        if (!hdr) {
@@ -1649,15 +1650,19 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                                goto drop;
                        }
 
+                       len = __le16_to_cpu(hdr->slen);
                } else {
+                       struct hci_iso_data_hdr *hdr;
+
                        hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
                        if (!hdr) {
                                BT_ERR("Frame is too short (len %d)", skb->len);
                                goto drop;
                        }
+
+                       len = __le16_to_cpu(hdr->slen);
                }
 
-               len    = __le16_to_cpu(hdr->slen);
                flags  = hci_iso_data_flags(len);
                len    = hci_iso_data_len(len);
 
index adfc3ea..49926f5 100644 (file)
@@ -708,6 +708,17 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 }
 EXPORT_SYMBOL_GPL(l2cap_chan_del);
 
+static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
+                                l2cap_chan_func_t func, void *data)
+{
+       struct l2cap_chan *chan, *l;
+
+       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+               if (chan->ident == id)
+                       func(chan, data);
+       }
+}
+
 static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
                              void *data)
 {
@@ -775,23 +786,9 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
 
 static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
 {
-       struct l2cap_conn *conn = chan->conn;
-       struct l2cap_ecred_conn_rsp rsp;
-       u16 result;
-
-       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
-               result = L2CAP_CR_LE_AUTHORIZATION;
-       else
-               result = L2CAP_CR_LE_BAD_PSM;
-
        l2cap_state_change(chan, BT_DISCONN);
 
-       memset(&rsp, 0, sizeof(rsp));
-
-       rsp.result  = cpu_to_le16(result);
-
-       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
-                      &rsp);
+       __l2cap_ecred_conn_rsp_defer(chan);
 }
 
 static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
@@ -846,7 +843,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
                                        break;
                                case L2CAP_MODE_EXT_FLOWCTL:
                                        l2cap_chan_ecred_connect_reject(chan);
-                                       break;
+                                       return;
                                }
                        }
                }
@@ -3938,43 +3935,86 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
                       &rsp);
 }
 
-void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
+static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
 {
+       int *result = data;
+
+       if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
+               return;
+
+       switch (chan->state) {
+       case BT_CONNECT2:
+               /* If channel still pending accept add to result */
+               (*result)++;
+               return;
+       case BT_CONNECTED:
+               return;
+       default:
+               /* If not connected or pending accept it has been refused */
+               *result = -ECONNREFUSED;
+               return;
+       }
+}
+
+struct l2cap_ecred_rsp_data {
        struct {
                struct l2cap_ecred_conn_rsp rsp;
-               __le16 dcid[5];
+               __le16 scid[L2CAP_ECRED_MAX_CID];
        } __packed pdu;
+       int count;
+};
+
+static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
+{
+       struct l2cap_ecred_rsp_data *rsp = data;
+
+       if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
+               return;
+
+       /* Reset ident so only one response is sent */
+       chan->ident = 0;
+
+       /* Include all channels pending with the same ident */
+       if (!rsp->pdu.rsp.result)
+               rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
+       else
+               l2cap_chan_del(chan, ECONNRESET);
+}
+
+void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
+{
        struct l2cap_conn *conn = chan->conn;
-       u16 ident = chan->ident;
-       int i = 0;
+       struct l2cap_ecred_rsp_data data;
+       u16 id = chan->ident;
+       int result = 0;
 
-       if (!ident)
+       if (!id)
                return;
 
-       BT_DBG("chan %p ident %d", chan, ident);
+       BT_DBG("chan %p id %d", chan, id);
 
-       pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
-       pdu.rsp.mps     = cpu_to_le16(chan->mps);
-       pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
-       pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
+       memset(&data, 0, sizeof(data));
 
-       mutex_lock(&conn->chan_lock);
+       data.pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
+       data.pdu.rsp.mps     = cpu_to_le16(chan->mps);
+       data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
+       data.pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
 
-       list_for_each_entry(chan, &conn->chan_l, list) {
-               if (chan->ident != ident)
-                       continue;
+       /* Verify that all channels are ready */
+       __l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
 
-               /* Reset ident so only one response is sent */
-               chan->ident = 0;
+       if (result > 0)
+               return;
 
-               /* Include all channels pending with the same ident */
-               pdu.dcid[i++] = cpu_to_le16(chan->scid);
-       }
+       if (result < 0)
+               data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
 
-       mutex_unlock(&conn->chan_lock);
+       /* Build response */
+       __l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
 
-       l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP,
-                       sizeof(pdu.rsp) + i * sizeof(__le16), &pdu);
+       l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
+                      sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
+                      &data.pdu);
 }
 
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
@@ -6078,6 +6118,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
                __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
 
                chan->ident = cmd->ident;
+               chan->mode = L2CAP_MODE_EXT_FLOWCTL;
 
                if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
                        l2cap_state_change(chan, BT_CONNECT2);
index 7add66f..249dc67 100644 (file)
@@ -4639,12 +4639,6 @@ static int set_mgmt_mesh_func(struct sock *sk, struct hci_dev *hdev,
                                       MGMT_OP_SET_EXP_FEATURE,
                                       MGMT_STATUS_INVALID_INDEX);
 
-       /* Changes can only be made when controller is powered down */
-       if (hdev_is_powered(hdev))
-               return mgmt_cmd_status(sk, hdev->id,
-                                      MGMT_OP_SET_EXP_FEATURE,
-                                      MGMT_STATUS_REJECTED);
-
        /* Parameters are limited to a single octet */
        if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
                return mgmt_cmd_status(sk, hdev->id,
@@ -9363,7 +9357,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
        { add_ext_adv_data,        MGMT_ADD_EXT_ADV_DATA_SIZE,
                                                HCI_MGMT_VAR_LEN },
        { add_adv_patterns_monitor_rssi,
-                                  MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE },
+                                  MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE,
+                                               HCI_MGMT_VAR_LEN },
        { set_mesh,                MGMT_SET_MESH_RECEIVER_SIZE,
                                                HCI_MGMT_VAR_LEN },
        { mesh_features,           MGMT_MESH_READ_FEATURES_SIZE },
index b5737e4..528d4b3 100644 (file)
@@ -720,7 +720,10 @@ __diag_ignore_all("-Wmissing-prototypes",
  * @ctx: XDP context pointer.
  * @timestamp: Return value pointer.
  *
- * Returns 0 on success or ``-errno`` on error.
+ * Return:
+ * * Returns 0 on success or ``-errno`` on error.
+ * * ``-EOPNOTSUPP`` : means device driver does not implement kfunc
+ * * ``-ENODATA``    : means no RX-timestamp available for this frame
  */
 __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
 {
@@ -732,7 +735,10 @@ __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *tim
  * @ctx: XDP context pointer.
  * @hash: Return value pointer.
  *
- * Returns 0 on success or ``-errno`` on error.
+ * Return:
+ * * Returns 0 on success or ``-errno`` on error.
+ * * ``-EOPNOTSUPP`` : means device driver doesn't implement kfunc
+ * * ``-ENODATA``    : means no RX-hash available for this frame
  */
 __bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash)
 {
index b2fba1a..5105a5f 100644 (file)
@@ -114,7 +114,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
                skb = nskb;
        }
 
-       dev_sw_netstats_rx_add(skb->dev, skb->len);
+       dev_sw_netstats_rx_add(skb->dev, skb->len + ETH_HLEN);
 
        if (dsa_skb_defer_rx_timestamp(p, skb))
                return 0;
index 10239da..cacdafb 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/dsa/brcm.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 
@@ -252,6 +253,7 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
 static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
                                        struct net_device *dev)
 {
+       int len = BRCM_LEG_TAG_LEN;
        int source_port;
        u8 *brcm_tag;
 
@@ -266,12 +268,16 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
        if (!skb->dev)
                return NULL;
 
+       /* VLAN tag is added by BCM63xx internal switch */
+       if (netdev_uses_dsa(skb->dev))
+               len += VLAN_HLEN;
+
        /* Remove Broadcom tag and update checksum */
-       skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
+       skb_pull_rcsum(skb, len);
 
        dsa_default_offload_fwd_mark(skb);
 
-       dsa_strip_etype_header(skb, BRCM_LEG_TAG_LEN);
+       dsa_strip_etype_header(skb, len);
 
        return skb;
 }
index ffff46c..e55a202 100644 (file)
@@ -552,7 +552,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                truncate = true;
        }
 
-       nhoff = skb_network_header(skb) - skb_mac_header(skb);
+       nhoff = skb_network_offset(skb);
        if (skb->protocol == htons(ETH_P_IP) &&
            (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
                truncate = true;
@@ -561,7 +561,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                int thoff;
 
                if (skb_transport_header_was_set(skb))
-                       thoff = skb_transport_header(skb) - skb_mac_header(skb);
+                       thoff = skb_transport_offset(skb);
                else
                        thoff = nhoff + sizeof(struct ipv6hdr);
                if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
index 89f5f0f..a4ecfc9 100644 (file)
@@ -959,7 +959,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                truncate = true;
        }
 
-       nhoff = skb_network_header(skb) - skb_mac_header(skb);
+       nhoff = skb_network_offset(skb);
        if (skb->protocol == htons(ETH_P_IP) &&
            (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
                truncate = true;
@@ -968,7 +968,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                int thoff;
 
                if (skb_transport_header_was_set(skb))
-                       thoff = skb_transport_header(skb) - skb_mac_header(skb);
+                       thoff = skb_transport_offset(skb);
                else
                        thoff = nhoff + sizeof(struct ipv6hdr);
                if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
index ecc232e..e082582 100644 (file)
@@ -1284,6 +1284,9 @@ struct ieee80211_local {
        struct list_head active_txqs[IEEE80211_NUM_ACS];
        u16 schedule_round[IEEE80211_NUM_ACS];
 
+       /* serializes ieee80211_handle_wake_tx_queue */
+       spinlock_t handle_wake_tx_queue_lock;
+
        u16 airtime_flags;
        u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
        u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
index 8465288..ddf2b78 100644 (file)
@@ -802,6 +802,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
        local->aql_threshold = IEEE80211_AQL_THRESHOLD;
        atomic_set(&local->aql_total_pending_airtime, 0);
 
+       spin_lock_init(&local->handle_wake_tx_queue_lock);
+
        INIT_LIST_HEAD(&local->chanctx_list);
        mutex_init(&local->chanctx_mtx);
 
index f7fdfe7..e8de500 100644 (file)
@@ -2765,17 +2765,6 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
            mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
                return RX_DROP_MONITOR;
 
-       /* Frame has reached destination.  Don't forward */
-       if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
-               goto rx_accept;
-
-       if (!ifmsh->mshcfg.dot11MeshForwarding) {
-               if (is_multicast_ether_addr(eth->h_dest))
-                       goto rx_accept;
-
-               return RX_DROP_MONITOR;
-       }
-
        /* forward packet */
        if (sdata->crypto_tx_tailroom_needed_cnt)
                tailroom = IEEE80211_ENCRYPT_TAILROOM;
@@ -2814,6 +2803,17 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
                rcu_read_unlock();
        }
 
+       /* Frame has reached destination.  Don't forward */
+       if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
+               goto rx_accept;
+
+       if (!ifmsh->mshcfg.dot11MeshForwarding) {
+               if (is_multicast_ether_addr(eth->h_dest))
+                       goto rx_accept;
+
+               return RX_DROP_MONITOR;
+       }
+
        skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
 
        ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
index 1a28fe5..3aceb3b 100644 (file)
@@ -314,6 +314,8 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
        struct ieee80211_txq *queue;
 
+       spin_lock(&local->handle_wake_tx_queue_lock);
+
        /* Use ieee80211_next_txq() for airtime fairness accounting */
        ieee80211_txq_schedule_start(hw, txq->ac);
        while ((queue = ieee80211_next_txq(hw, txq->ac))) {
@@ -321,6 +323,7 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
                ieee80211_return_txq(hw, queue, false);
        }
        ieee80211_txq_schedule_end(hw, txq->ac);
+       spin_unlock(&local->handle_wake_tx_queue_lock);
 }
 EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
 
index a12c636..1601be5 100644 (file)
@@ -147,6 +147,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                           struct sta_info *sta, struct sk_buff *skb)
 {
+       const struct ethhdr *eth = (void *)skb->data;
        struct mac80211_qos_map *qos_map;
        bool qos;
 
@@ -154,8 +155,9 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
        skb_get_hash(skb);
 
        /* all mesh/ocb stations are required to support WME */
-       if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
-                   sdata->vif.type == NL80211_IFTYPE_OCB))
+       if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT &&
+           !is_multicast_ether_addr(eth->h_dest)) ||
+           (sdata->vif.type == NL80211_IFTYPE_OCB && sta))
                qos = true;
        else if (sta)
                qos = sta->sta.wme;
index 6c7c52e..212c5d5 100644 (file)
@@ -353,7 +353,9 @@ gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen,
        err = crypto_ahash_final(req);
        if (err)
                goto out_free_ahash;
-       memcpy(cksumout->data, checksumdata, cksumout->len);
+
+       memcpy(cksumout->data, checksumdata,
+              min_t(int, cksumout->len, crypto_ahash_digestsize(tfm)));
 
 out_free_ahash:
        ahash_request_free(req);
@@ -809,8 +811,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
        buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN;
        buf->len += GSS_KRB5_TOK_HDR_LEN;
 
-       /* Do the HMAC */
-       hmac.len = GSS_KRB5_MAX_CKSUM_LEN;
+       hmac.len = kctx->gk5e->cksumlength;
        hmac.data = buf->tail[0].iov_base + buf->tail[0].iov_len;
 
        /*
@@ -873,8 +874,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
        if (ret)
                goto out_err;
 
-       /* Calculate our hmac over the plaintext data */
-       our_hmac_obj.len = sizeof(our_hmac);
+       our_hmac_obj.len = kctx->gk5e->cksumlength;
        our_hmac_obj.data = our_hmac;
        ret = gss_krb5_checksum(ahash, NULL, 0, &subbuf, 0, &our_hmac_obj);
        if (ret)
index 4681e8e..02207e8 100644 (file)
@@ -150,10 +150,11 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
 
 static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 {
-       u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom;
        bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
-       u64 npgs, addr = mr->addr, size = mr->len;
-       unsigned int chunks, chunks_rem;
+       u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
+       u64 addr = mr->addr, size = mr->len;
+       u32 chunks_rem, npgs_rem;
+       u64 chunks, npgs;
        int err;
 
        if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
@@ -188,8 +189,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        if (npgs > U32_MAX)
                return -EINVAL;
 
-       chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem);
-       if (chunks == 0)
+       chunks = div_u64_rem(size, chunk_size, &chunks_rem);
+       if (!chunks || chunks > U32_MAX)
                return -EINVAL;
 
        if (!unaligned_chunks && chunks_rem)
@@ -202,7 +203,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        umem->headroom = headroom;
        umem->chunk_size = chunk_size;
        umem->chunks = chunks;
-       umem->npgs = (u32)npgs;
+       umem->npgs = npgs;
        umem->pgs = NULL;
        umem->user = NULL;
        umem->flags = mr->flags;
index f33e61a..1e5d2ee 100755 (executable)
@@ -114,7 +114,6 @@ cat << EOF
 #define __IGNORE_truncate
 #define __IGNORE_stat
 #define __IGNORE_lstat
-#define __IGNORE_fstat
 #define __IGNORE_fcntl
 #define __IGNORE_fadvise64
 #define __IGNORE_newfstatat
@@ -255,6 +254,9 @@ cat << EOF
 /* 64-bit ports never needed these, and new 32-bit ports can use statx */
 #define __IGNORE_fstat64
 #define __IGNORE_fstatat64
+
+/* Newer ports are not required to provide fstat in favor of statx */
+#define __IGNORE_fstat
 EOF
 }
 
index 2da4404..07a0ef2 100644 (file)
@@ -38,9 +38,12 @@ static void cache_requested_key(struct key *key)
 #ifdef CONFIG_KEYS_REQUEST_CACHE
        struct task_struct *t = current;
 
-       key_put(t->cached_requested_key);
-       t->cached_requested_key = key_get(key);
-       set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
+       /* Do not cache key if it is a kernel thread */
+       if (!(t->flags & PF_KTHREAD)) {
+               key_put(t->cached_requested_key);
+               t->cached_requested_key = key_get(key);
+               set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
+       }
 #endif
 }
 
index f68e2e9..a2c484c 100755 (executable)
@@ -87,10 +87,14 @@ xfail grep -i "error" $OUTFILE
 
 echo "Max node number check"
 
-echo -n > $TEMPCONF
-for i in `seq 1 1024` ; do
-   echo "node$i" >> $TEMPCONF
-done
+awk '
+BEGIN {
+  for (i = 0; i < 26; i += 1)
+      printf("%c\n", 65 + i % 26)
+  for (i = 26; i < 8192; i += 1)
+      printf("%c%c%c\n", 65 + i % 26, 65 + (i / 26) % 26, 65 + (i / 26 / 26))
+}
+' > $TEMPCONF
 xpass $BOOTCONF -a $TEMPCONF $INITRD
 
 echo "badnode" >> $TEMPCONF
index fbaf683..e4d0566 100644 (file)
@@ -20,8 +20,8 @@
 /* make sure libbpf doesn't use kernel-only integer typedefs */
 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
 
-/* prevent accidental re-addition of reallocarray()/strlcpy() */
-#pragma GCC poison reallocarray strlcpy
+/* prevent accidental re-addition of reallocarray() */
+#pragma GCC poison reallocarray
 
 #include "libbpf.h"
 #include "btf.h"
index 90764a8..32536e1 100644 (file)
@@ -200,7 +200,7 @@ def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None):
     if seq is None:
         seq = random.randint(1, 1024)
     nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
-    genlmsg = struct.pack("bbH", genl_cmd, genl_version, 0)
+    genlmsg = struct.pack("BBH", genl_cmd, genl_version, 0)
     return nlmsg + genlmsg
 
 
@@ -264,7 +264,7 @@ class GenlMsg:
         self.hdr = nl_msg.raw[0:4]
         self.raw = nl_msg.raw[4:]
 
-        self.genl_cmd, self.genl_version, _ = struct.unpack("bbH", self.hdr)
+        self.genl_cmd, self.genl_version, _ = struct.unpack("BBH", self.hdr)
 
         self.raw_attrs = NlAttrs(self.raw)
 
@@ -358,7 +358,7 @@ class YnlFamily(SpecFamily):
                 raw >>= 1
                 i += 1
         else:
-            value = enum['entries'][raw - i]
+            value = enum.entries_by_val[raw - i].name
         rsp[attr_spec['name']] = value
 
     def _decode(self, attrs, space):
diff --git a/tools/testing/selftests/bpf/prog_tests/uninit_stack.c b/tools/testing/selftests/bpf/prog_tests/uninit_stack.c
new file mode 100644 (file)
index 0000000..e64c719
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+#include "uninit_stack.skel.h"
+
+void test_uninit_stack(void)
+{
+       RUN_TESTS(uninit_stack);
+}
index b3b326b..6dab9cf 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) 2021 Facebook */
 #include "vmlinux.h"
 #include <bpf/bpf_helpers.h>
+#define vm_flags vm_start
 
 char _license[] SEC("license") = "GPL";
 
index 591104e..e96b901 100644 (file)
@@ -5,12 +5,10 @@
 #include <errno.h>
 #include <linux/capability.h>
 
-struct kernel_cap_struct {
-       __u64 val;
-} __attribute__((preserve_access_index));
+typedef struct { unsigned long long val; } kernel_cap_t;
 
 struct cred {
-       struct kernel_cap_struct cap_effective;
+       kernel_cap_t cap_effective;
 } __attribute__((preserve_access_index));
 
 char _license[] SEC("license") = "GPL";
@@ -18,8 +16,8 @@ char _license[] SEC("license") = "GPL";
 SEC("lsm.s/userns_create")
 int BPF_PROG(test_userns_create, const struct cred *cred, int ret)
 {
-       struct kernel_cap_struct caps = cred->cap_effective;
-       __u64 cap_mask = BIT_LL(CAP_SYS_ADMIN);
+       kernel_cap_t caps = cred->cap_effective;
+       __u64 cap_mask = 1ULL << CAP_SYS_ADMIN;
 
        if (ret)
                return 0;
index 98327bd..8fba3f3 100644 (file)
@@ -5,12 +5,12 @@
 #include "bpf_misc.h"
 
 struct Small {
-       int x;
+       long x;
 };
 
 struct Big {
-       int x;
-       int y;
+       long x;
+       long y;
 };
 
 __noinline int foo(const struct Big *big)
@@ -22,7 +22,7 @@ __noinline int foo(const struct Big *big)
 }
 
 SEC("cgroup_skb/ingress")
-__failure __msg("invalid indirect read from stack")
+__failure __msg("invalid indirect access to stack")
 int global_func10(struct __sk_buff *skb)
 {
        const struct Small small = {.x = skb->len };
diff --git a/tools/testing/selftests/bpf/progs/uninit_stack.c b/tools/testing/selftests/bpf/progs/uninit_stack.c
new file mode 100644 (file)
index 0000000..8a40347
--- /dev/null
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+/* Read an uninitialized value from stack at a fixed offset */
+SEC("socket")
+__naked int read_uninit_stack_fixed_off(void *ctx)
+{
+       asm volatile ("                                 \
+               r0 = 0;                                 \
+               /* force stack depth to be 128 */       \
+               *(u64*)(r10 - 128) = r1;                \
+               r1 = *(u8 *)(r10 - 8 );                 \
+               r0 += r1;                               \
+               r1 = *(u8 *)(r10 - 11);                 \
+               r1 = *(u8 *)(r10 - 13);                 \
+               r1 = *(u8 *)(r10 - 15);                 \
+               r1 = *(u16*)(r10 - 16);                 \
+               r1 = *(u32*)(r10 - 32);                 \
+               r1 = *(u64*)(r10 - 64);                 \
+               /* read from a spill of a wrong size, it is a separate  \
+                * branch in check_stack_read_fixed_off()               \
+                */                                     \
+               *(u32*)(r10 - 72) = r1;                 \
+               r1 = *(u64*)(r10 - 72);                 \
+               r0 = 0;                                 \
+               exit;                                   \
+"
+                     ::: __clobber_all);
+}
+
+/* Read an uninitialized value from stack at a variable offset */
+SEC("socket")
+__naked int read_uninit_stack_var_off(void *ctx)
+{
+       asm volatile ("                                 \
+               call %[bpf_get_prandom_u32];            \
+               /* force stack depth to be 64 */        \
+               *(u64*)(r10 - 64) = r0;                 \
+               r0 = -r0;                               \
+               /* give r0 a range [-31, -1] */         \
+               if r0 s<= -32 goto exit_%=;             \
+               if r0 s>= 0 goto exit_%=;               \
+               /* access stack using r0 */             \
+               r1 = r10;                               \
+               r1 += r0;                               \
+               r2 = *(u8*)(r1 + 0);                    \
+exit_%=:       r0 = 0;                                 \
+               exit;                                   \
+"
+                     :
+                     : __imm(bpf_get_prandom_u32)
+                     : __clobber_all);
+}
+
+static __noinline void dummy(void) {}
+
+/* Pass a pointer to uninitialized stack memory to a helper.
+ * Passed memory block should be marked as STACK_MISC after helper call.
+ */
+SEC("socket")
+__log_level(7) __msg("fp-104=mmmmmmmm")
+__naked int helper_uninit_to_misc(void *ctx)
+{
+       asm volatile ("                                 \
+               /* force stack depth to be 128 */       \
+               *(u64*)(r10 - 128) = r1;                \
+               r1 = r10;                               \
+               r1 += -128;                             \
+               r2 = 32;                                \
+               call %[bpf_trace_printk];               \
+               /* Call to dummy() forces print_verifier_state(..., true),      \
+                * thus showing the stack state, matched by __msg().            \
+                */                                     \
+               call %[dummy];                          \
+               r0 = 0;                                 \
+               exit;                                   \
+"
+                     :
+                     : __imm(bpf_trace_printk),
+                       __imm(dummy)
+                     : __clobber_all);
+}
+
+char _license[] SEC("license") = "GPL";
index 9d99392..289ed20 100644 (file)
         * that fp-8 stack slot was unused in the fall-through
         * branch and will accept the program incorrectly
         */
-       BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 2, 2),
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_JMP_IMM(BPF_JGT, BPF_REG_0, 2, 2),
        BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
        BPF_JMP_IMM(BPF_JA, 0, 0, 0),
        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
        BPF_LD_MAP_FD(BPF_REG_1, 0),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .fixup_map_hash_48b = { 6 },
-       .errstr = "invalid indirect read from stack R2 off -8+0 size 8",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_XDP,
+       .fixup_map_hash_48b = { 7 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -8+0 size 8",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "calls: ctx read at start of subprog",
index a6c869a..9c48858 100644 (file)
 {
        "helper access to variable memory: stack, bitwise AND, zero included",
        .insns = {
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
-       BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
-       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
-       BPF_MOV64_IMM(BPF_REG_3, 0),
-       BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
+       /* set max stack size */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
+       /* set r3 to a random value */
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+       /* use bitwise AND to limit r3 range to [0, 64] */
+       BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 64),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
+       BPF_MOV64_IMM(BPF_REG_4, 0),
+       /* Call bpf_ringbuf_output(), it is one of a few helper functions with
+        * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
+        * For unpriv this should signal an error, because memory at &fp[-64] is
+        * not initialized.
+        */
+       BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
        BPF_EXIT_INSN(),
        },
-       .errstr = "invalid indirect read from stack R1 off -64+0 size 64",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .fixup_map_ringbuf = { 4 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "helper access to variable memory: stack, bitwise AND + JMP, wrong max",
 {
        "helper access to variable memory: stack, JMP, no min check",
        .insns = {
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
-       BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
-       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
-       BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3),
-       BPF_MOV64_IMM(BPF_REG_3, 0),
-       BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
+       /* set max stack size */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
+       /* set r3 to a random value */
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+       /* use JMP to limit r3 range to [0, 64] */
+       BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 64, 6),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
+       BPF_MOV64_IMM(BPF_REG_4, 0),
+       /* Call bpf_ringbuf_output(), it is one of a few helper functions with
+        * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
+        * For unpriv this should signal an error, because memory at &fp[-64] is
+        * not initialized.
+        */
+       BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .errstr = "invalid indirect read from stack R1 off -64+0 size 64",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .fixup_map_ringbuf = { 4 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "helper access to variable memory: stack, JMP (signed), no min check",
 {
        "helper access to variable memory: 8 bytes leak",
        .insns = {
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
-       BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
+       /* set max stack size */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
+       /* set r3 to a random value */
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
+       /* Note: fp[-32] left uninitialized */
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
-       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
-       BPF_MOV64_IMM(BPF_REG_3, 0),
-       BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
+       /* Limit r3 range to [1, 64] */
+       BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 63),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1),
+       BPF_MOV64_IMM(BPF_REG_4, 0),
+       /* Call bpf_ringbuf_output(), it is one of a few helper functions with
+        * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
+        * For unpriv this should signal an error, because memory region [1, 64]
+        * at &fp[-64] is not fully initialized.
+        */
+       BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .errstr = "invalid indirect read from stack R1 off -64+32 size 64",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .fixup_map_ringbuf = { 3 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -64+32 size 64",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "helper access to variable memory: 8 bytes no leak (init memory)",
index 070893f..02d9e00 100644 (file)
                /* bpf_strtoul() */
                BPF_EMIT_CALL(BPF_FUNC_strtoul),
 
-               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_MOV64_IMM(BPF_REG_0, 0),
                BPF_EXIT_INSN(),
        },
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
-       .errstr = "invalid indirect read from stack R4 off -16+4 size 8",
+       .result_unpriv = REJECT,
+       .errstr_unpriv = "invalid indirect read from stack R4 off -16+4 size 8",
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "ARG_PTR_TO_LONG misaligned",
index d63fd89..745d6b5 100644 (file)
                BPF_EXIT_INSN(),
        },
        .fixup_map_hash_8b = { 3 },
-       .errstr = "invalid read from stack off -16+0 size 8",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .errstr_unpriv = "invalid read from stack off -16+0 size 8",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "precision tracking for u32 spill/fill",
        BPF_EXIT_INSN(),
        },
        .flags = BPF_F_TEST_STATE_FREQ,
-       .errstr = "invalid read from stack off -8+1 size 8",
-       .result = REJECT,
+       .errstr_unpriv = "invalid read from stack off -8+1 size 8",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
index d11d0b2..108dd3e 100644 (file)
        .result = ACCEPT,
 },
 {
-       "sk_storage_get(map, skb->sk, &stack_value, 1): partially init stack_value",
-       .insns = {
-       BPF_MOV64_IMM(BPF_REG_2, 0),
-       BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -8),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
-       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
-       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       BPF_MOV64_IMM(BPF_REG_4, 1),
-       BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -8),
-       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
-       BPF_LD_MAP_FD(BPF_REG_1, 0),
-       BPF_EMIT_CALL(BPF_FUNC_sk_storage_get),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       },
-       .fixup_sk_storage_map = { 14 },
-       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
-       .result = REJECT,
-       .errstr = "invalid indirect read from stack",
-},
-{
        "bpf_map_lookup_elem(smap, &key)",
        .insns = {
        BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0),
index 9bb302d..d1463bf 100644 (file)
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .result = REJECT,
-       .errstr = "invalid read from stack off -4+0 size 4",
-       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result_unpriv = REJECT,
+       .errstr_unpriv = "invalid read from stack off -4+0 size 4",
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "Spill a u32 const scalar.  Refill as u16.  Offset to skb->data",
index d37f512..b183e26 100644 (file)
        .prog_type = BPF_PROG_TYPE_LWT_IN,
 },
 {
-       "indirect variable-offset stack access, max_off+size > max_initialized",
-       .insns = {
-       /* Fill only the second from top 8 bytes of the stack. */
-       BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
-       /* Get an unknown value. */
-       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
-       /* Make it small and 4-byte aligned. */
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
-       BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
-       /* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
-        * which. fp-12 size 8 is partially uninitialized stack.
-        */
-       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
-       /* Dereference it indirectly. */
-       BPF_LD_MAP_FD(BPF_REG_1, 0),
-       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       },
-       .fixup_map_hash_8b = { 5 },
-       .errstr = "invalid indirect read from stack R2 var_off",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_LWT_IN,
-},
-{
        "indirect variable-offset stack access, min_off < min_initialized",
        .insns = {
        /* Fill only the top 8 bytes of the stack. */
        .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
 },
 {
-       "indirect variable-offset stack access, uninitialized",
-       .insns = {
-       BPF_MOV64_IMM(BPF_REG_2, 6),
-       BPF_MOV64_IMM(BPF_REG_3, 28),
-       /* Fill the top 16 bytes of the stack. */
-       BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0),
-       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
-       /* Get an unknown value. */
-       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0),
-       /* Make it small and 4-byte aligned. */
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4),
-       BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
-       /* Add it to fp.  We now have either fp-12 or fp-16, we don't know
-        * which, but either way it points to initialized stack.
-        */
-       BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
-       BPF_MOV64_IMM(BPF_REG_5, 8),
-       /* Dereference it indirectly. */
-       BPF_EMIT_CALL(BPF_FUNC_getsockopt),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       },
-       .errstr = "invalid indirect read from stack R4 var_off",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_SOCK_OPS,
-},
-{
        "indirect variable-offset stack access, ok",
        .insns = {
        /* Fill the top 16 bytes of the stack. */
index f466a09..bc91bef 100644 (file)
@@ -163,9 +163,8 @@ TEST_F(mdwe, mprotect_WRITE_EXEC)
 
 TEST_F(mdwe, mmap_FIXED)
 {
-       void *p, *p2;
+       void *p;
 
-       p2 = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0);
        self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0);
        ASSERT_NE(self->p, MAP_FAILED);
 
index 625e429..d884fd6 100644 (file)
 #include <sys/auxv.h>
 #include <sys/mman.h>
 #include <sys/shm.h>
+#include <sys/ptrace.h>
 #include <sys/syscall.h>
 #include <sys/wait.h>
+#include <sys/uio.h>
 
 #include "../kselftest.h" /* For __cpuid_count() */
 
@@ -583,6 +585,13 @@ static void test_dynamic_state(void)
        _exit(0);
 }
 
+static inline int __compare_tiledata_state(struct xsave_buffer *xbuf1, struct xsave_buffer *xbuf2)
+{
+       return memcmp(&xbuf1->bytes[xtiledata.xbuf_offset],
+                     &xbuf2->bytes[xtiledata.xbuf_offset],
+                     xtiledata.size);
+}
+
 /*
  * Save current register state and compare it to @xbuf1.'
  *
@@ -599,9 +608,7 @@ static inline bool __validate_tiledata_regs(struct xsave_buffer *xbuf1)
                fatal_error("failed to allocate XSAVE buffer\n");
 
        xsave(xbuf2, XFEATURE_MASK_XTILEDATA);
-       ret = memcmp(&xbuf1->bytes[xtiledata.xbuf_offset],
-                    &xbuf2->bytes[xtiledata.xbuf_offset],
-                    xtiledata.size);
+       ret = __compare_tiledata_state(xbuf1, xbuf2);
 
        free(xbuf2);
 
@@ -826,6 +833,99 @@ static void test_context_switch(void)
        free(finfo);
 }
 
+/* Ptrace test */
+
+/*
+ * Make sure the ptracee has the expanded kernel buffer on the first
+ * use. Then, initialize the state before performing the state
+ * injection from the ptracer.
+ */
+static inline void ptracee_firstuse_tiledata(void)
+{
+       load_rand_tiledata(stashed_xsave);
+       init_xtiledata();
+}
+
+/*
+ * Ptracer injects the randomized tile data state. It also reads
+ * before and after that, which will execute the kernel's state copy
+ * functions. So, the tester is advised to double-check any emitted
+ * kernel messages.
+ */
+static void ptracer_inject_tiledata(pid_t target)
+{
+       struct xsave_buffer *xbuf;
+       struct iovec iov;
+
+       xbuf = alloc_xbuf();
+       if (!xbuf)
+               fatal_error("unable to allocate XSAVE buffer");
+
+       printf("\tRead the init'ed tiledata via ptrace().\n");
+
+       iov.iov_base = xbuf;
+       iov.iov_len = xbuf_size;
+
+       memset(stashed_xsave, 0, xbuf_size);
+
+       if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
+               fatal_error("PTRACE_GETREGSET");
+
+       if (!__compare_tiledata_state(stashed_xsave, xbuf))
+               printf("[OK]\tThe init'ed tiledata was read from ptracee.\n");
+       else
+               printf("[FAIL]\tThe init'ed tiledata was not read from ptracee.\n");
+
+       printf("\tInject tiledata via ptrace().\n");
+
+       load_rand_tiledata(xbuf);
+
+       memcpy(&stashed_xsave->bytes[xtiledata.xbuf_offset],
+              &xbuf->bytes[xtiledata.xbuf_offset],
+              xtiledata.size);
+
+       if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
+               fatal_error("PTRACE_SETREGSET");
+
+       if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
+               fatal_error("PTRACE_GETREGSET");
+
+       if (!__compare_tiledata_state(stashed_xsave, xbuf))
+               printf("[OK]\tTiledata was correctly written to ptracee.\n");
+       else
+               printf("[FAIL]\tTiledata was not correctly written to ptracee.\n");
+}
+
+static void test_ptrace(void)
+{
+       pid_t child;
+       int status;
+
+       child = fork();
+       if (child < 0) {
+               err(1, "fork");
+       } else if (!child) {
+               if (ptrace(PTRACE_TRACEME, 0, NULL, NULL))
+                       err(1, "PTRACE_TRACEME");
+
+               ptracee_firstuse_tiledata();
+
+               raise(SIGTRAP);
+               _exit(0);
+       }
+
+       do {
+               wait(&status);
+       } while (WSTOPSIG(status) != SIGTRAP);
+
+       ptracer_inject_tiledata(child);
+
+       ptrace(PTRACE_DETACH, child, NULL, NULL);
+       wait(&status);
+       if (!WIFEXITED(status) || WEXITSTATUS(status))
+               err(1, "ptrace test");
+}
+
 int main(void)
 {
        /* Check hardware availability at first */
@@ -846,6 +946,8 @@ int main(void)
        ctxtswtest_config.num_threads = 5;
        test_context_switch();
 
+       test_ptrace();
+
        clearhandler(SIGILL);
        free_stashed_xsave();