Merge tag 'v5.2-rc6' into rdma.git for-next
authorJason Gunthorpe <jgg@mellanox.com>
Sat, 29 Jun 2019 00:18:23 +0000 (21:18 -0300)
committerJason Gunthorpe <jgg@mellanox.com>
Sat, 29 Jun 2019 00:18:23 +0000 (21:18 -0300)
For dependencies in next patches.

Resolve conflicts:
- Use uverbs_get_cleared_udata() with new cq allocation flow
- Continue to delete nes despite SPDX conflict
- Resolve list appends in mlx5_command_str()
- Use u16 for vport_rule stuff
- Resolve list appends in struct ib_client

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
41 files changed:
1  2 
MAINTAINERS
drivers/infiniband/Kconfig
drivers/infiniband/core/cq.c
drivers/infiniband/core/device.c
drivers/infiniband/core/mr_pool.c
drivers/infiniband/core/rw.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_std_types_cq.c
drivers/infiniband/core/uverbs_std_types_mr.c
drivers/infiniband/hw/efa/efa_com_cmd.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hfi1/pio.c
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/hns/Kconfig
drivers/infiniband/hw/hns/Makefile
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/mlx5/ib_rep.c
drivers/infiniband/hw/mlx5/ib_rep.h
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/qib/qib_verbs.c
drivers/infiniband/sw/rdmavt/mr.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/ulp/ipoib/Kconfig
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/ecpf.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/nvme/host/rdma.c
include/linux/mlx5/eswitch.h
include/net/devlink.h
include/rdma/ib_verbs.h
include/rdma/mr_pool.h
include/rdma/rw.h
net/core/devlink.c

diff --combined MAINTAINERS
@@@ -364,7 -364,7 +364,7 @@@ F: drivers/acpi/fan.
  
  ACPI FOR ARM64 (ACPI/arm64)
  M:    Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
- M:    Hanjun Guo <hanjun.guo@linaro.org>
+ M:    Hanjun Guo <guohanjun@huawei.com>
  M:    Sudeep Holla <sudeep.holla@arm.com>
  L:    linux-acpi@vger.kernel.org
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -696,6 -696,7 +696,7 @@@ F: drivers/input/mouse/alps.
  ALTERA I2C CONTROLLER DRIVER
  M:    Thor Thayer <thor.thayer@linux.intel.com>
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-altera.txt
  F:    drivers/i2c/busses/i2c-altera.c
  
  ALTERA MAILBOX DRIVER
@@@ -1174,6 -1175,7 +1175,7 @@@ S:      Maintaine
  F:    Documentation/devicetree/bindings/arm/arm-boards
  F:    Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt
  F:    Documentation/devicetree/bindings/clock/arm-integrator.txt
+ F:    Documentation/devicetree/bindings/i2c/i2c-versatile.txt
  F:    Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
  F:    Documentation/devicetree/bindings/mtd/arm-versatile.txt
  F:    arch/arm/mach-integrator/
@@@ -1233,7 -1235,7 +1235,7 @@@ F:      arch/arm/lib/floppydma.
  F:    arch/arm/include/asm/floppy.h
  
  ARM PMU PROFILING AND DEBUGGING
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  M:    Mark Rutland <mark.rutland@arm.com>
  S:    Maintained
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1305,7 -1307,7 +1307,7 @@@ F:      Documentation/devicetree/bindings/in
  F:    drivers/irqchip/irq-vic.c
  
  ARM SMMU DRIVERS
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  R:    Robin Murphy <robin.murphy@arm.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
@@@ -1781,6 -1783,7 +1783,7 @@@ ARM/LPC18XX ARCHITECTUR
  M:    Vladimir Zapolskiy <vz@mleia.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt
  F:    arch/arm/boot/dts/lpc43*
  F:    drivers/i2c/busses/i2c-lpc2k.c
  F:    drivers/memory/pl172.c
@@@ -1794,6 -1797,7 +1797,7 @@@ M:      Sylvain Lemieux <slemieux.tyco@gmail
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  T:    git git://github.com/vzapolskiy/linux-lpc32xx.git
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-pnx.txt
  F:    arch/arm/boot/dts/lpc32*
  F:    arch/arm/mach-lpc32xx/
  F:    drivers/i2c/busses/i2c-pnx.c
@@@ -1918,6 -1922,8 +1922,8 @@@ ARM/NOMADIK/U300/Ux500 ARCHITECTURE
  M:    Linus Walleij <linus.walleij@linaro.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
+ F:    Documentation/devicetree/bindings/i2c/i2c-stu300.txt
  F:    arch/arm/mach-nomadik/
  F:    arch/arm/mach-u300/
  F:    arch/arm/mach-ux500/
@@@ -2079,7 -2085,7 +2085,7 @@@ F:      drivers/tty/serial/msm_serial.
  F:    drivers/usb/dwc3/dwc3-qcom.c
  F:    include/dt-bindings/*/qcom*
  F:    include/linux/*/qcom*
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
  
  ARM/RADISYS ENP2611 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
@@@ -2140,6 -2146,7 +2146,7 @@@ L:      linux-arm-kernel@lists.infradead.or
  L:    linux-rockchip@lists.infradead.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
  F:    arch/arm/boot/dts/rk3*
  F:    arch/arm/boot/dts/rv1108*
  F:    arch/arm/mach-rockchip/
@@@ -2275,6 -2282,7 +2282,7 @@@ M:      Patrice Chotard <patrice.chotard@st.
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.stlinux.com
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-st.txt
  F:    arch/arm/mach-sti/
  F:    arch/arm/boot/dts/sti*
  F:    drivers/char/hw_random/st-rng.c
@@@ -2466,6 -2474,7 +2474,7 @@@ ARM/VT8500 ARM ARCHITECTUR
  M:    Tony Prisk <linux@prisktech.co.nz>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-wmt.txt
  F:    arch/arm/mach-vt8500/
  F:    drivers/clocksource/timer-vt8500.c
  F:    drivers/i2c/busses/i2c-wmt.c
@@@ -2531,6 -2540,8 +2540,8 @@@ F:      drivers/cpuidle/cpuidle-zynq.
  F:    drivers/block/xsysace.c
  N:    zynq
  N:    xilinx
+ F:    Documentation/devicetree/bindings/i2c/i2c-cadence.txt
+ F:    Documentation/devicetree/bindings/i2c/i2c-xiic.txt
  F:    drivers/clocksource/timer-cadence-ttc.c
  F:    drivers/i2c/busses/i2c-cadence.c
  F:    drivers/mmc/host/sdhci-of-arasan.c
@@@ -2539,7 -2550,7 +2550,7 @@@ F:      drivers/i2c/busses/i2c-xiic.
  
  ARM64 PORT (AARCH64 ARCHITECTURE)
  M:    Catalin Marinas <catalin.marinas@arm.com>
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
  S:    Maintained
@@@ -2627,7 -2638,7 +2638,7 @@@ F:      Documentation/devicetree/bindings/ee
  F:    drivers/misc/eeprom/at24.c
  
  ATA OVER ETHERNET (AOE) DRIVER
- M:    "Ed L. Cashin" <ed.cashin@acm.org>
+ M:    "Justin Sanders" <justin@coraid.com>
  W:    http://www.openaoe.org/
  S:    Supported
  F:    Documentation/aoe/
@@@ -2723,7 -2734,7 +2734,7 @@@ S:      Maintaine
  F:    drivers/net/wireless/atmel/atmel*
  
  ATOMIC INFRASTRUCTURE
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  M:    Peter Zijlstra <peterz@infradead.org>
  R:    Boqun Feng <boqun.feng@gmail.com>
  L:    linux-kernel@vger.kernel.org
@@@ -2768,7 -2779,7 +2779,7 @@@ AVIA HX711 ANALOG DIGITAL CONVERTER II
  M:    Andreas Klinger <ak@it-klinger.de>
  L:    linux-iio@vger.kernel.org
  S:    Maintained
- F:    Documentation/devicetree/bindings/iio/adc/avia-hx711.txt
+ F:    Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
  F:    drivers/iio/adc/hx711.c
  
  AX.25 NETWORK LAYER
@@@ -3049,8 -3060,9 +3060,9 @@@ S:      Maintaine
  F:    arch/riscv/net/
  
  BPF JIT for S390
- M:    Martin Schwidefsky <schwidefsky@de.ibm.com>
  M:    Heiko Carstens <heiko.carstens@de.ibm.com>
+ M:    Vasily Gorbik <gor@linux.ibm.com>
+ M:    Christian Borntraeger <borntraeger@de.ibm.com>
  L:    netdev@vger.kernel.org
  L:    bpf@vger.kernel.org
  S:    Maintained
@@@ -3109,7 -3121,7 +3121,7 @@@ F:      arch/arm/mach-bcm
  
  BROADCOM BCM2835 ARM ARCHITECTURE
  M:    Eric Anholt <eric@anholt.net>
- M:    Stefan Wahren <stefan.wahren@i2se.com>
+ M:    Stefan Wahren <wahrenst@gmx.net>
  L:    linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  T:    git git://github.com/anholt/linux
@@@ -6222,7 -6234,6 +6234,6 @@@ F:      include/linux/ipmi-fru.
  K:    fmc_d.*register
  
  FPGA MANAGER FRAMEWORK
- M:    Alan Tull <atull@kernel.org>
  M:    Moritz Fischer <mdf@kernel.org>
  L:    linux-fpga@vger.kernel.org
  S:    Maintained
@@@ -7341,6 -7352,7 +7352,7 @@@ I2C MV64XXX MARVELL AND ALLWINNER DRIVE
  M:    Gregory CLEMENT <gregory.clement@bootlin.com>
  L:    linux-i2c@vger.kernel.org
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
  F:    drivers/i2c/busses/i2c-mv64xxx.c
  
  I2C OVER PARALLEL PORT
@@@ -8553,7 -8565,7 +8565,7 @@@ S:      Odd Fixe
  
  KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
  M:    "J. Bruce Fields" <bfields@fieldses.org>
- M:    Jeff Layton <jlayton@kernel.org>
+ M:    Chuck Lever <chuck.lever@oracle.com>
  L:    linux-nfs@vger.kernel.org
  W:    http://nfs.sourceforge.net/
  T:    git git://linux-nfs.org/~bfields/linux.git
@@@ -8611,14 -8623,12 +8623,12 @@@ F:   arch/x86/include/asm/svm.
  F:    arch/x86/kvm/svm.c
  
  KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
- M:    Christoffer Dall <christoffer.dall@arm.com>
  M:    Marc Zyngier <marc.zyngier@arm.com>
  R:    James Morse <james.morse@arm.com>
  R:    Julien Thierry <julien.thierry@arm.com>
  R:    Suzuki K Pouloze <suzuki.poulose@arm.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  L:    kvmarm@lists.cs.columbia.edu
- W:    http://systems.cs.columbia.edu/projects/kvm-arm
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
  S:    Maintained
  F:    arch/arm/include/uapi/asm/kvm*
@@@ -9110,7 -9120,7 +9120,7 @@@ F:      drivers/misc/lkdtm/
  LINUX KERNEL MEMORY CONSISTENCY MODEL (LKMM)
  M:    Alan Stern <stern@rowland.harvard.edu>
  M:    Andrea Parri <andrea.parri@amarulasolutions.com>
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  M:    Peter Zijlstra <peterz@infradead.org>
  M:    Boqun Feng <boqun.feng@gmail.com>
  M:    Nicholas Piggin <npiggin@gmail.com>
@@@ -9218,7 -9228,7 +9228,7 @@@ F:      Documentation/admin-guide/LSM/LoadPi
  LOCKING PRIMITIVES
  M:    Peter Zijlstra <peterz@infradead.org>
  M:    Ingo Molnar <mingo@redhat.com>
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  L:    linux-kernel@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
  S:    Maintained
@@@ -10539,7 -10549,7 +10549,7 @@@ F:   arch/arm/boot/dts/mmp
  F:    arch/arm/mach-mmp/
  
  MMU GATHER AND TLB INVALIDATION
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  M:    "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
  M:    Andrew Morton <akpm@linux-foundation.org>
  M:    Nick Piggin <npiggin@gmail.com>
@@@ -10830,6 -10840,14 +10840,6 @@@ F:  driver/net/net_failover.
  F:    include/net/net_failover.h
  F:    Documentation/networking/net_failover.rst
  
 -NETEFFECT IWARP RNIC DRIVER (IW_NES)
 -M:    Faisal Latif <faisal.latif@intel.com>
 -L:    linux-rdma@vger.kernel.org
 -W:    http://www.intel.com/Products/Server/Adapters/Server-Cluster/Server-Cluster-overview.htm
 -S:    Supported
 -F:    drivers/infiniband/hw/nes/
 -F:    include/uapi/rdma/nes-abi.h
 -
  NETEM NETWORK EMULATOR
  M:    Stephen Hemminger <stephen@networkplumber.org>
  L:    netem@lists.linux-foundation.org (moderated for non-subscribers)
@@@ -11060,10 -11078,8 +11070,8 @@@ S:  Supporte
  F:    drivers/net/ethernet/qlogic/netxen/
  
  NFC SUBSYSTEM
- M:    Samuel Ortiz <sameo@linux.intel.com>
- L:    linux-wireless@vger.kernel.org
- L:    linux-nfc@lists.01.org (subscribers-only)
- S:    Supported
+ L:    netdev@vger.kernel.org
+ S:    Orphan
  F:    net/nfc/
  F:    include/net/nfc/
  F:    include/uapi/linux/nfc.h
@@@ -11220,7 -11236,7 +11228,7 @@@ F:   drivers/video/fbdev/riva
  F:    drivers/video/fbdev/nvidia/
  
  NVM EXPRESS DRIVER
- M:    Keith Busch <keith.busch@intel.com>
+ M:    Keith Busch <kbusch@kernel.org>
  M:    Jens Axboe <axboe@fb.com>
  M:    Christoph Hellwig <hch@lst.de>
  M:    Sagi Grimberg <sagi@grimberg.me>
@@@ -11720,6 -11736,7 +11728,7 @@@ M:   Peter Korsgaard <peter@korsgaard.com
  M:    Andrew Lunn <andrew@lunn.ch>
  L:    linux-i2c@vger.kernel.org
  S:    Maintained
+ F:    Documentation/devicetree/bindings/i2c/i2c-ocores.txt
  F:    Documentation/i2c/busses/i2c-ocores
  F:    drivers/i2c/busses/i2c-ocores.c
  F:    include/linux/platform_data/i2c-ocores.h
@@@ -12021,7 -12038,7 +12030,7 @@@ S:   Maintaine
  F:    drivers/pci/controller/dwc/*layerscape*
  
  PCI DRIVER FOR GENERIC OF HOSTS
- M:    Will Deacon <will.deacon@arm.com>
+ M:    Will Deacon <will@kernel.org>
  L:    linux-pci@vger.kernel.org
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
@@@ -13039,7 -13056,6 +13048,6 @@@ F:   Documentation/devicetree/bindings/ne
  
  QUALCOMM GENERIC INTERFACE I2C DRIVER
  M:    Alok Chauhan <alokc@codeaurora.org>
- M:    Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
  L:    linux-i2c@vger.kernel.org
  L:    linux-arm-msm@vger.kernel.org
  S:    Supported
@@@ -13359,6 -13375,7 +13367,7 @@@ F:   drivers/clk/renesas
  RENESAS EMEV2 I2C DRIVER
  M:    Wolfram Sang <wsa+renesas@sang-engineering.com>
  S:    Supported
+ F:    Documentation/devicetree/bindings/i2c/i2c-emev2.txt
  F:    drivers/i2c/busses/i2c-emev2.c
  
  RENESAS ETHERNET DRIVERS
@@@ -13380,6 -13397,8 +13389,8 @@@ F:   drivers/iio/adc/rcar-gyroadc.
  RENESAS R-CAR I2C DRIVERS
  M:    Wolfram Sang <wsa+renesas@sang-engineering.com>
  S:    Supported
+ F:    Documentation/devicetree/bindings/i2c/i2c-rcar.txt
+ F:    Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
  F:    drivers/i2c/busses/i2c-rcar.c
  F:    drivers/i2c/busses/i2c-sh_mobile.c
  
@@@ -13610,8 -13629,9 +13621,9 @@@ S:   Maintaine
  F:    drivers/video/fbdev/savage/
  
  S390
- M:    Martin Schwidefsky <schwidefsky@de.ibm.com>
  M:    Heiko Carstens <heiko.carstens@de.ibm.com>
+ M:    Vasily Gorbik <gor@linux.ibm.com>
+ M:    Christian Borntraeger <borntraeger@de.ibm.com>
  L:    linux-s390@vger.kernel.org
  W:    http://www.ibm.com/developerworks/linux/linux390/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git
@@@ -14314,6 -14334,15 +14326,15 @@@ S: Supporte
  K:    sifive
  N:    sifive
  
+ SIFIVE FU540 SYSTEM-ON-CHIP
+ M:    Paul Walmsley <paul.walmsley@sifive.com>
+ M:    Palmer Dabbelt <palmer@sifive.com>
+ L:    linux-riscv@lists.infradead.org
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pjw/sifive.git
+ S:    Supported
+ K:    fu540
+ N:    fu540
  SILEAD TOUCHSCREEN DRIVER
  M:    Hans de Goede <hdegoede@redhat.com>
  L:    linux-input@vger.kernel.org
@@@ -14345,7 -14374,7 +14366,7 @@@ SIMPLEFB FB DRIVE
  M:    Hans de Goede <hdegoede@redhat.com>
  L:    linux-fbdev@vger.kernel.org
  S:    Maintained
- F:    Documentation/devicetree/bindings/display/simple-framebuffer.txt
+ F:    Documentation/devicetree/bindings/display/simple-framebuffer.yaml
  F:    drivers/video/fbdev/simplefb.c
  F:    include/linux/platform_data/simplefb.h
  
@@@ -14374,7 -14403,7 +14395,7 @@@ F:   lib/test_siphash.
  F:    include/linux/siphash.h
  
  SIOX
- M:    Gavin Schenk <g.schenk@eckelmann.de>
+ M:    Thorsten Scherer <t.scherer@eckelmann.de>
  M:    Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
  R:    Pengutronix Kernel Team <kernel@pengutronix.de>
  S:    Supported
@@@ -14973,7 -15002,7 +14994,7 @@@ S:   Odd Fixe
  F:    drivers/net/ethernet/adaptec/starfire*
  
  STEC S1220 SKD DRIVER
- M:    Bart Van Assche <bart.vanassche@wdc.com>
+ M:    Damien Le Moal <Damien.LeMoal@wdc.com>
  L:    linux-block@vger.kernel.org
  S:    Maintained
  F:    drivers/block/skd*[ch]
@@@ -15668,6 -15697,7 +15689,7 @@@ R:   Bartosz Golaszewski <bgolaszewski@ba
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
  S:    Supported
+ F:    Documentation/devicetree/bindings/i2c/i2c-davinci.txt
  F:    arch/arm/mach-davinci/
  F:    drivers/i2c/busses/i2c-davinci.c
  F:    arch/arm/boot/dts/da850*
@@@ -17289,7 -17319,7 +17311,7 @@@ F:   Documentation/ABI/stable/sysfs-hyper
  F:    Documentation/ABI/testing/sysfs-hypervisor-xen
  
  XEN NETWORK BACKEND DRIVER
- M:    Wei Liu <wei.liu2@citrix.com>
+ M:    Wei Liu <wei.liu@kernel.org>
  M:    Paul Durrant <paul.durrant@citrix.com>
  L:    xen-devel@lists.xenproject.org (moderated for non-subscribers)
  L:    netdev@vger.kernel.org
@@@ -17371,6 -17401,7 +17393,7 @@@ M:   Jan Glauber <jglauber@cavium.com
  L:    linux-i2c@vger.kernel.org
  W:    http://www.cavium.com
  S:    Supported
+ F:    Documentation/devicetree/bindings/i2c/i2c-xlp9xx.txt
  F:    drivers/i2c/busses/i2c-xlp9xx.c
  
  XRA1403 GPIO EXPANDER
@@@ -1,3 -1,4 +1,4 @@@
+ # SPDX-License-Identifier: GPL-2.0-only
  menuconfig INFINIBAND
        tristate "InfiniBand support"
        depends on HAS_IOMEM && HAS_DMA
@@@ -35,6 -36,17 +36,6 @@@ config INFINIBAND_USER_ACCES
          libibverbs, libibcm and a hardware driver library from
          rdma-core <https://github.com/linux-rdma/rdma-core>.
  
 -config INFINIBAND_USER_ACCESS_UCM
 -      tristate "Userspace CM (UCM, DEPRECATED)"
 -      depends on BROKEN || COMPILE_TEST
 -      depends on INFINIBAND_USER_ACCESS
 -      help
 -        The UCM module has known security flaws, which no one is
 -        interested to fix. The user-space part of this code was
 -        dropped from the upstream a long time ago.
 -
 -        This option is DEPRECATED and planned to be removed.
 -
  config INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI
        bool "Allow experimental legacy verbs in new ioctl uAPI  (EXPERIMENTAL)"
        depends on INFINIBAND_USER_ACCESS
@@@ -86,6 -98,7 +87,6 @@@ source "drivers/infiniband/hw/efa/Kconf
  source "drivers/infiniband/hw/i40iw/Kconfig"
  source "drivers/infiniband/hw/mlx4/Kconfig"
  source "drivers/infiniband/hw/mlx5/Kconfig"
 -source "drivers/infiniband/hw/nes/Kconfig"
  source "drivers/infiniband/hw/ocrdma/Kconfig"
  source "drivers/infiniband/hw/vmw_pvrdma/Kconfig"
  source "drivers/infiniband/hw/usnic/Kconfig"
@@@ -1,14 -1,6 +1,6 @@@
+ // SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2015 HGST, a Western Digital Company.
-  *
-  * This program is free software; you can redistribute it and/or modify it
-  * under the terms and conditions of the GNU General Public License,
-  * version 2, as published by the Free Software Foundation.
-  *
-  * This program is distributed in the hope it will be useful, but WITHOUT
-  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  * more details.
   */
  #include <linux/module.h>
  #include <linux/err.h>
@@@ -121,7 -113,7 +113,7 @@@ static void ib_cq_completion_workqueue(
  }
  
  /**
 - * __ib_alloc_cq - allocate a completion queue
 + * __ib_alloc_cq_user - allocate a completion queue
   * @dev:              device to allocate the CQ for
   * @private:          driver private data, accessible from cq->cq_context
   * @nr_cqe:           number of CQEs to allocate
@@@ -147,26 -139,23 +139,26 @@@ struct ib_cq *__ib_alloc_cq_user(struc
        struct ib_cq *cq;
        int ret = -ENOMEM;
  
 -      cq = dev->ops.create_cq(dev, &cq_attr, NULL);
 -      if (IS_ERR(cq))
 -              return cq;
 +      cq = rdma_zalloc_drv_obj(dev, ib_cq);
 +      if (!cq)
 +              return ERR_PTR(ret);
  
        cq->device = dev;
 -      cq->uobject = NULL;
 -      cq->event_handler = NULL;
        cq->cq_context = private;
        cq->poll_ctx = poll_ctx;
        atomic_set(&cq->usecnt, 0);
  
        cq->wc = kmalloc_array(IB_POLL_BATCH, sizeof(*cq->wc), GFP_KERNEL);
        if (!cq->wc)
 -              goto out_destroy_cq;
 +              goto out_free_cq;
  
        cq->res.type = RDMA_RESTRACK_CQ;
        rdma_restrack_set_task(&cq->res, caller);
 +
 +      ret = dev->ops.create_cq(cq, &cq_attr, NULL);
 +      if (ret)
 +              goto out_free_wc;
 +
        rdma_restrack_kadd(&cq->res);
  
        switch (cq->poll_ctx) {
                break;
        default:
                ret = -EINVAL;
 -              goto out_free_wc;
 +              goto out_destroy_cq;
        }
  
        return cq;
  
 -out_free_wc:
 -      kfree(cq->wc);
 -      rdma_restrack_del(&cq->res);
  out_destroy_cq:
 +      rdma_restrack_del(&cq->res);
        cq->device->ops.destroy_cq(cq, udata);
 +out_free_wc:
 +      kfree(cq->wc);
 +out_free_cq:
 +      kfree(cq);
        return ERR_PTR(ret);
  }
  EXPORT_SYMBOL(__ib_alloc_cq_user);
  
  /**
 - * ib_free_cq - free a completion queue
 + * ib_free_cq_user - free a completion queue
   * @cq:               completion queue to free.
   * @udata:    User data or NULL for kernel object
   */
  void ib_free_cq_user(struct ib_cq *cq, struct ib_udata *udata)
  {
 -      int ret;
 -
        if (WARN_ON_ONCE(atomic_read(&cq->usecnt)))
                return;
  
                WARN_ON_ONCE(1);
        }
  
 -      kfree(cq->wc);
        rdma_restrack_del(&cq->res);
 -      ret = cq->device->ops.destroy_cq(cq, udata);
 -      WARN_ON_ONCE(ret);
 +      cq->device->ops.destroy_cq(cq, udata);
 +      kfree(cq->wc);
 +      kfree(cq);
  }
  EXPORT_SYMBOL(ib_free_cq_user);
@@@ -270,7 -270,7 +270,7 @@@ struct ib_port_data_rcu 
        struct ib_port_data pdata[];
  };
  
 -static int ib_device_check_mandatory(struct ib_device *device)
 +static void ib_device_check_mandatory(struct ib_device *device)
  {
  #define IB_MANDATORY_FUNC(x) { offsetof(struct ib_device_ops, x), #x }
        static const struct {
                        break;
                }
        }
 -
 -      return 0;
  }
  
  /*
@@@ -373,7 -375,7 +373,7 @@@ struct ib_device *ib_device_get_by_name
        down_read(&devices_rwsem);
        device = __ib_device_get_by_name(name);
        if (device && driver_id != RDMA_DRIVER_UNKNOWN &&
 -          device->driver_id != driver_id)
 +          device->ops.driver_id != driver_id)
                device = NULL;
  
        if (device) {
@@@ -407,27 -409,44 +407,44 @@@ static int rename_compat_devs(struct ib
  
  int ib_device_rename(struct ib_device *ibdev, const char *name)
  {
+       unsigned long index;
+       void *client_data;
        int ret;
  
        down_write(&devices_rwsem);
        if (!strcmp(name, dev_name(&ibdev->dev))) {
-               ret = 0;
-               goto out;
+               up_write(&devices_rwsem);
+               return 0;
        }
  
        if (__ib_device_get_by_name(name)) {
-               ret = -EEXIST;
-               goto out;
+               up_write(&devices_rwsem);
+               return -EEXIST;
        }
  
        ret = device_rename(&ibdev->dev, name);
-       if (ret)
-               goto out;
+       if (ret) {
+               up_write(&devices_rwsem);
+               return ret;
+       }
        strlcpy(ibdev->name, name, IB_DEVICE_NAME_MAX);
        ret = rename_compat_devs(ibdev);
- out:
-       up_write(&devices_rwsem);
-       return ret;
+       downgrade_write(&devices_rwsem);
+       down_read(&ibdev->client_data_rwsem);
+       xan_for_each_marked(&ibdev->client_data, index, client_data,
+                           CLIENT_DATA_REGISTERED) {
+               struct ib_client *client = xa_load(&clients, index);
+               if (!client || !client->rename)
+                       continue;
+               client->rename(ibdev, client_data);
+       }
+       up_read(&ibdev->client_data_rwsem);
+       up_read(&devices_rwsem);
+       return 0;
  }
  
  static int alloc_name(struct ib_device *ibdev, const char *name)
@@@ -472,14 -491,15 +489,15 @@@ static void ib_device_release(struct de
  
        free_netdevs(dev);
        WARN_ON(refcount_read(&dev->refcount));
-       ib_cache_release_one(dev);
-       ib_security_release_port_pkey_list(dev);
-       xa_destroy(&dev->compat_devs);
-       xa_destroy(&dev->client_data);
-       if (dev->port_data)
+       if (dev->port_data) {
+               ib_cache_release_one(dev);
+               ib_security_release_port_pkey_list(dev);
                kfree_rcu(container_of(dev->port_data, struct ib_port_data_rcu,
                                       pdata[0]),
                          rcu_head);
+       }
+       xa_destroy(&dev->compat_devs);
+       xa_destroy(&dev->client_data);
        kfree_rcu(dev, rcu_head);
  }
  
@@@ -1173,7 -1193,10 +1191,7 @@@ static int setup_device(struct ib_devic
        int ret;
  
        setup_dma_device(device);
 -
 -      ret = ib_device_check_mandatory(device);
 -      if (ret)
 -              return ret;
 +      ib_device_check_mandatory(device);
  
        ret = setup_port_data(device);
        if (ret) {
@@@ -1456,7 -1479,7 +1474,7 @@@ void ib_unregister_driver(enum rdma_dri
  
        down_read(&devices_rwsem);
        xa_for_each (&devices, index, ib_dev) {
 -              if (ib_dev->driver_id != driver_id)
 +              if (ib_dev->ops.driver_id != driver_id)
                        continue;
  
                get_device(&ib_dev->dev);
@@@ -1726,104 -1749,6 +1744,104 @@@ void ib_unregister_client(struct ib_cli
  }
  EXPORT_SYMBOL(ib_unregister_client);
  
 +static int __ib_get_global_client_nl_info(const char *client_name,
 +                                        struct ib_client_nl_info *res)
 +{
 +      struct ib_client *client;
 +      unsigned long index;
 +      int ret = -ENOENT;
 +
 +      down_read(&clients_rwsem);
 +      xa_for_each_marked (&clients, index, client, CLIENT_REGISTERED) {
 +              if (strcmp(client->name, client_name) != 0)
 +                      continue;
 +              if (!client->get_global_nl_info) {
 +                      ret = -EOPNOTSUPP;
 +                      break;
 +              }
 +              ret = client->get_global_nl_info(res);
 +              if (WARN_ON(ret == -ENOENT))
 +                      ret = -EINVAL;
 +              if (!ret && res->cdev)
 +                      get_device(res->cdev);
 +              break;
 +      }
 +      up_read(&clients_rwsem);
 +      return ret;
 +}
 +
 +static int __ib_get_client_nl_info(struct ib_device *ibdev,
 +                                 const char *client_name,
 +                                 struct ib_client_nl_info *res)
 +{
 +      unsigned long index;
 +      void *client_data;
 +      int ret = -ENOENT;
 +
 +      down_read(&ibdev->client_data_rwsem);
 +      xan_for_each_marked (&ibdev->client_data, index, client_data,
 +                           CLIENT_DATA_REGISTERED) {
 +              struct ib_client *client = xa_load(&clients, index);
 +
 +              if (!client || strcmp(client->name, client_name) != 0)
 +                      continue;
 +              if (!client->get_nl_info) {
 +                      ret = -EOPNOTSUPP;
 +                      break;
 +              }
 +              ret = client->get_nl_info(ibdev, client_data, res);
 +              if (WARN_ON(ret == -ENOENT))
 +                      ret = -EINVAL;
 +
 +              /*
 +               * The cdev is guaranteed valid as long as we are inside the
 +               * client_data_rwsem as remove_one can't be called. Keep it
 +               * valid for the caller.
 +               */
 +              if (!ret && res->cdev)
 +                      get_device(res->cdev);
 +              break;
 +      }
 +      up_read(&ibdev->client_data_rwsem);
 +
 +      return ret;
 +}
 +
 +/**
 + * ib_get_client_nl_info - Fetch the nl_info from a client
 + * @device - IB device
 + * @client_name - Name of the client
 + * @res - Result of the query
 + */
 +int ib_get_client_nl_info(struct ib_device *ibdev, const char *client_name,
 +                        struct ib_client_nl_info *res)
 +{
 +      int ret;
 +
 +      if (ibdev)
 +              ret = __ib_get_client_nl_info(ibdev, client_name, res);
 +      else
 +              ret = __ib_get_global_client_nl_info(client_name, res);
 +#ifdef CONFIG_MODULES
 +      if (ret == -ENOENT) {
 +              request_module("rdma-client-%s", client_name);
 +              if (ibdev)
 +                      ret = __ib_get_client_nl_info(ibdev, client_name, res);
 +              else
 +                      ret = __ib_get_global_client_nl_info(client_name, res);
 +      }
 +#endif
 +      if (ret) {
 +              if (ret == -ENOENT)
 +                      return -EOPNOTSUPP;
 +              return ret;
 +      }
 +
 +      if (WARN_ON(!res->cdev))
 +              return -EINVAL;
 +      return 0;
 +}
 +
  /**
   * ib_set_client_data - Set IB client context
   * @device:Device to set context for
@@@ -2028,6 -1953,9 +2046,9 @@@ static void free_netdevs(struct ib_devi
        unsigned long flags;
        unsigned int port;
  
+       if (!ib_dev->port_data)
+               return;
        rdma_for_each_port (ib_dev, port) {
                struct ib_port_data *pdata = &ib_dev->port_data[port];
                struct net_device *ndev;
@@@ -2111,7 -2039,7 +2132,7 @@@ struct ib_device *ib_device_get_by_netd
                                    (uintptr_t)ndev) {
                if (rcu_access_pointer(cur->netdev) == ndev &&
                    (driver_id == RDMA_DRIVER_UNKNOWN ||
 -                   cur->ib_dev->driver_id == driver_id) &&
 +                   cur->ib_dev->ops.driver_id == driver_id) &&
                    ib_device_try_get(cur->ib_dev)) {
                        res = cur->ib_dev;
                        break;
@@@ -2416,28 -2344,12 +2437,28 @@@ void ib_set_device_ops(struct ib_devic
  
  #define SET_OBJ_SIZE(ptr, name) SET_DEVICE_OP(ptr, size_##name)
  
 +      if (ops->driver_id != RDMA_DRIVER_UNKNOWN) {
 +              WARN_ON(dev_ops->driver_id != RDMA_DRIVER_UNKNOWN &&
 +                      dev_ops->driver_id != ops->driver_id);
 +              dev_ops->driver_id = ops->driver_id;
 +      }
 +      if (ops->owner) {
 +              WARN_ON(dev_ops->owner && dev_ops->owner != ops->owner);
 +              dev_ops->owner = ops->owner;
 +      }
 +      if (ops->uverbs_abi_ver)
 +              dev_ops->uverbs_abi_ver = ops->uverbs_abi_ver;
 +
 +      dev_ops->uverbs_no_driver_id_binding |=
 +              ops->uverbs_no_driver_id_binding;
 +
        SET_DEVICE_OP(dev_ops, add_gid);
        SET_DEVICE_OP(dev_ops, advise_mr);
        SET_DEVICE_OP(dev_ops, alloc_dm);
        SET_DEVICE_OP(dev_ops, alloc_fmr);
        SET_DEVICE_OP(dev_ops, alloc_hw_stats);
        SET_DEVICE_OP(dev_ops, alloc_mr);
 +      SET_DEVICE_OP(dev_ops, alloc_mr_integrity);
        SET_DEVICE_OP(dev_ops, alloc_mw);
        SET_DEVICE_OP(dev_ops, alloc_pd);
        SET_DEVICE_OP(dev_ops, alloc_rdma_netdev);
        SET_DEVICE_OP(dev_ops, iw_reject);
        SET_DEVICE_OP(dev_ops, iw_rem_ref);
        SET_DEVICE_OP(dev_ops, map_mr_sg);
 +      SET_DEVICE_OP(dev_ops, map_mr_sg_pi);
        SET_DEVICE_OP(dev_ops, map_phys_fmr);
        SET_DEVICE_OP(dev_ops, mmap);
        SET_DEVICE_OP(dev_ops, modify_ah);
        SET_DEVICE_OP(dev_ops, unmap_fmr);
  
        SET_OBJ_SIZE(dev_ops, ib_ah);
 +      SET_OBJ_SIZE(dev_ops, ib_cq);
        SET_OBJ_SIZE(dev_ops, ib_pd);
        SET_OBJ_SIZE(dev_ops, ib_srq);
        SET_OBJ_SIZE(dev_ops, ib_ucontext);
@@@ -1,14 -1,6 +1,6 @@@
+ // SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 HGST, a Western Digital Company.
-  *
-  * This program is free software; you can redistribute it and/or modify it
-  * under the terms and conditions of the GNU General Public License,
-  * version 2, as published by the Free Software Foundation.
-  *
-  * This program is distributed in the hope it will be useful, but WITHOUT
-  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  * more details.
   */
  #include <rdma/ib_verbs.h>
  #include <rdma/mr_pool.h>
@@@ -42,18 -34,14 +34,18 @@@ void ib_mr_pool_put(struct ib_qp *qp, s
  EXPORT_SYMBOL(ib_mr_pool_put);
  
  int ib_mr_pool_init(struct ib_qp *qp, struct list_head *list, int nr,
 -              enum ib_mr_type type, u32 max_num_sg)
 +              enum ib_mr_type type, u32 max_num_sg, u32 max_num_meta_sg)
  {
        struct ib_mr *mr;
        unsigned long flags;
        int ret, i;
  
        for (i = 0; i < nr; i++) {
 -              mr = ib_alloc_mr(qp->pd, type, max_num_sg);
 +              if (type == IB_MR_TYPE_INTEGRITY)
 +                      mr = ib_alloc_mr_integrity(qp->pd, max_num_sg,
 +                                                 max_num_meta_sg);
 +              else
 +                      mr = ib_alloc_mr(qp->pd, type, max_num_sg);
                if (IS_ERR(mr)) {
                        ret = PTR_ERR(mr);
                        goto out;
@@@ -1,14 -1,6 +1,6 @@@
+ // SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 HGST, a Western Digital Company.
-  *
-  * This program is free software; you can redistribute it and/or modify it
-  * under the terms and conditions of the GNU General Public License,
-  * version 2, as published by the Free Software Foundation.
-  *
-  * This program is distributed in the hope it will be useful, but WITHOUT
-  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  * more details.
   */
  #include <linux/moduleparam.h>
  #include <linux/slab.h>
@@@ -59,34 -51,10 +51,34 @@@ static inline bool rdma_rw_io_needs_mr(
        return false;
  }
  
 -static inline u32 rdma_rw_fr_page_list_len(struct ib_device *dev)
 +static inline u32 rdma_rw_fr_page_list_len(struct ib_device *dev,
 +                                         bool pi_support)
  {
 +      u32 max_pages;
 +
 +      if (pi_support)
 +              max_pages = dev->attrs.max_pi_fast_reg_page_list_len;
 +      else
 +              max_pages = dev->attrs.max_fast_reg_page_list_len;
 +
        /* arbitrary limit to avoid allocating gigantic resources */
 -      return min_t(u32, dev->attrs.max_fast_reg_page_list_len, 256);
 +      return min_t(u32, max_pages, 256);
 +}
 +
 +static inline int rdma_rw_inv_key(struct rdma_rw_reg_ctx *reg)
 +{
 +      int count = 0;
 +
 +      if (reg->mr->need_inval) {
 +              reg->inv_wr.opcode = IB_WR_LOCAL_INV;
 +              reg->inv_wr.ex.invalidate_rkey = reg->mr->lkey;
 +              reg->inv_wr.next = &reg->reg_wr.wr;
 +              count++;
 +      } else {
 +              reg->inv_wr.next = NULL;
 +      }
 +
 +      return count;
  }
  
  /* Caller must have zero-initialized *reg. */
@@@ -94,8 -62,7 +86,8 @@@ static int rdma_rw_init_one_mr(struct i
                struct rdma_rw_reg_ctx *reg, struct scatterlist *sg,
                u32 sg_cnt, u32 offset)
  {
 -      u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
 +      u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device,
 +                                                  qp->integrity_en);
        u32 nents = min(sg_cnt, pages_per_mr);
        int count = 0, ret;
  
        if (!reg->mr)
                return -EAGAIN;
  
 -      if (reg->mr->need_inval) {
 -              reg->inv_wr.opcode = IB_WR_LOCAL_INV;
 -              reg->inv_wr.ex.invalidate_rkey = reg->mr->lkey;
 -              reg->inv_wr.next = &reg->reg_wr.wr;
 -              count++;
 -      } else {
 -              reg->inv_wr.next = NULL;
 -      }
 +      count += rdma_rw_inv_key(reg);
  
        ret = ib_map_mr_sg(reg->mr, sg, nents, &offset, PAGE_SIZE);
        if (ret < 0 || ret < nents) {
@@@ -128,8 -102,7 +120,8 @@@ static int rdma_rw_init_mr_wrs(struct r
                u64 remote_addr, u32 rkey, enum dma_data_direction dir)
  {
        struct rdma_rw_reg_ctx *prev = NULL;
 -      u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
 +      u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device,
 +                                                  qp->integrity_en);
        int i, j, ret = 0, count = 0;
  
        ctx->nr_ops = (sg_cnt + pages_per_mr - 1) / pages_per_mr;
@@@ -370,14 -343,13 +362,14 @@@ int rdma_rw_ctx_signature_init(struct r
                u64 remote_addr, u32 rkey, enum dma_data_direction dir)
  {
        struct ib_device *dev = qp->pd->device;
 -      u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
 +      u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device,
 +                                                  qp->integrity_en);
        struct ib_rdma_wr *rdma_wr;
 -      struct ib_send_wr *prev_wr = NULL;
        int count = 0, ret;
  
        if (sg_cnt > pages_per_mr || prot_sg_cnt > pages_per_mr) {
 -              pr_err("SG count too large\n");
 +              pr_err("SG count too large: sg_cnt=%d, prot_sg_cnt=%d, pages_per_mr=%d\n",
 +                     sg_cnt, prot_sg_cnt, pages_per_mr);
                return -EINVAL;
        }
  
                return -ENOMEM;
        sg_cnt = ret;
  
 -      ret = ib_dma_map_sg(dev, prot_sg, prot_sg_cnt, dir);
 -      if (!ret) {
 -              ret = -ENOMEM;
 -              goto out_unmap_sg;
 +      if (prot_sg_cnt) {
 +              ret = ib_dma_map_sg(dev, prot_sg, prot_sg_cnt, dir);
 +              if (!ret) {
 +                      ret = -ENOMEM;
 +                      goto out_unmap_sg;
 +              }
 +              prot_sg_cnt = ret;
        }
 -      prot_sg_cnt = ret;
  
        ctx->type = RDMA_RW_SIG_MR;
        ctx->nr_ops = 1;
 -      ctx->sig = kcalloc(1, sizeof(*ctx->sig), GFP_KERNEL);
 -      if (!ctx->sig) {
 +      ctx->reg = kcalloc(1, sizeof(*ctx->reg), GFP_KERNEL);
 +      if (!ctx->reg) {
                ret = -ENOMEM;
                goto out_unmap_prot_sg;
        }
  
 -      ret = rdma_rw_init_one_mr(qp, port_num, &ctx->sig->data, sg, sg_cnt, 0);
 -      if (ret < 0)
 -              goto out_free_ctx;
 -      count += ret;
 -      prev_wr = &ctx->sig->data.reg_wr.wr;
 -
 -      ret = rdma_rw_init_one_mr(qp, port_num, &ctx->sig->prot,
 -                                prot_sg, prot_sg_cnt, 0);
 -      if (ret < 0)
 -              goto out_destroy_data_mr;
 -      count += ret;
 -
 -      if (ctx->sig->prot.inv_wr.next)
 -              prev_wr->next = &ctx->sig->prot.inv_wr;
 -      else
 -              prev_wr->next = &ctx->sig->prot.reg_wr.wr;
 -      prev_wr = &ctx->sig->prot.reg_wr.wr;
 -
 -      ctx->sig->sig_mr = ib_mr_pool_get(qp, &qp->sig_mrs);
 -      if (!ctx->sig->sig_mr) {
 +      ctx->reg->mr = ib_mr_pool_get(qp, &qp->sig_mrs);
 +      if (!ctx->reg->mr) {
                ret = -EAGAIN;
 -              goto out_destroy_prot_mr;
 +              goto out_free_ctx;
        }
  
 -      if (ctx->sig->sig_mr->need_inval) {
 -              memset(&ctx->sig->sig_inv_wr, 0, sizeof(ctx->sig->sig_inv_wr));
 +      count += rdma_rw_inv_key(ctx->reg);
  
 -              ctx->sig->sig_inv_wr.opcode = IB_WR_LOCAL_INV;
 -              ctx->sig->sig_inv_wr.ex.invalidate_rkey = ctx->sig->sig_mr->rkey;
 +      memcpy(ctx->reg->mr->sig_attrs, sig_attrs, sizeof(struct ib_sig_attrs));
  
 -              prev_wr->next = &ctx->sig->sig_inv_wr;
 -              prev_wr = &ctx->sig->sig_inv_wr;
 +      ret = ib_map_mr_sg_pi(ctx->reg->mr, sg, sg_cnt, NULL, prot_sg,
 +                            prot_sg_cnt, NULL, SZ_4K);
 +      if (unlikely(ret)) {
 +              pr_err("failed to map PI sg (%d)\n", sg_cnt + prot_sg_cnt);
 +              goto out_destroy_sig_mr;
        }
  
 -      ctx->sig->sig_wr.wr.opcode = IB_WR_REG_SIG_MR;
 -      ctx->sig->sig_wr.wr.wr_cqe = NULL;
 -      ctx->sig->sig_wr.wr.sg_list = &ctx->sig->data.sge;
 -      ctx->sig->sig_wr.wr.num_sge = 1;
 -      ctx->sig->sig_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
 -      ctx->sig->sig_wr.sig_attrs = sig_attrs;
 -      ctx->sig->sig_wr.sig_mr = ctx->sig->sig_mr;
 -      if (prot_sg_cnt)
 -              ctx->sig->sig_wr.prot = &ctx->sig->prot.sge;
 -      prev_wr->next = &ctx->sig->sig_wr.wr;
 -      prev_wr = &ctx->sig->sig_wr.wr;
 +      ctx->reg->reg_wr.wr.opcode = IB_WR_REG_MR_INTEGRITY;
 +      ctx->reg->reg_wr.wr.wr_cqe = NULL;
 +      ctx->reg->reg_wr.wr.num_sge = 0;
 +      ctx->reg->reg_wr.wr.send_flags = 0;
 +      ctx->reg->reg_wr.access = IB_ACCESS_LOCAL_WRITE;
 +      if (rdma_protocol_iwarp(qp->device, port_num))
 +              ctx->reg->reg_wr.access |= IB_ACCESS_REMOTE_WRITE;
 +      ctx->reg->reg_wr.mr = ctx->reg->mr;
 +      ctx->reg->reg_wr.key = ctx->reg->mr->lkey;
        count++;
  
 -      ctx->sig->sig_sge.addr = 0;
 -      ctx->sig->sig_sge.length = ctx->sig->data.sge.length;
 -      if (sig_attrs->wire.sig_type != IB_SIG_TYPE_NONE)
 -              ctx->sig->sig_sge.length += ctx->sig->prot.sge.length;
 +      ctx->reg->sge.addr = ctx->reg->mr->iova;
 +      ctx->reg->sge.length = ctx->reg->mr->length;
 +      if (sig_attrs->wire.sig_type == IB_SIG_TYPE_NONE)
 +              ctx->reg->sge.length -= ctx->reg->mr->sig_attrs->meta_length;
  
 -      rdma_wr = &ctx->sig->data.wr;
 -      rdma_wr->wr.sg_list = &ctx->sig->sig_sge;
 +      rdma_wr = &ctx->reg->wr;
 +      rdma_wr->wr.sg_list = &ctx->reg->sge;
        rdma_wr->wr.num_sge = 1;
        rdma_wr->remote_addr = remote_addr;
        rdma_wr->rkey = rkey;
                rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
        else
                rdma_wr->wr.opcode = IB_WR_RDMA_READ;
 -      prev_wr->next = &rdma_wr->wr;
 -      prev_wr = &rdma_wr->wr;
 +      ctx->reg->reg_wr.wr.next = &rdma_wr->wr;
        count++;
  
        return count;
  
 -out_destroy_prot_mr:
 -      if (prot_sg_cnt)
 -              ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->prot.mr);
 -out_destroy_data_mr:
 -      ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->data.mr);
 +out_destroy_sig_mr:
 +      ib_mr_pool_put(qp, &qp->sig_mrs, ctx->reg->mr);
  out_free_ctx:
 -      kfree(ctx->sig);
 +      kfree(ctx->reg);
  out_unmap_prot_sg:
 -      ib_dma_unmap_sg(dev, prot_sg, prot_sg_cnt, dir);
 +      if (prot_sg_cnt)
 +              ib_dma_unmap_sg(dev, prot_sg, prot_sg_cnt, dir);
  out_unmap_sg:
        ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
        return ret;
@@@ -499,8 -491,22 +491,8 @@@ struct ib_send_wr *rdma_rw_ctx_wrs(stru
  
        switch (ctx->type) {
        case RDMA_RW_SIG_MR:
 -              rdma_rw_update_lkey(&ctx->sig->data, true);
 -              if (ctx->sig->prot.mr)
 -                      rdma_rw_update_lkey(&ctx->sig->prot, true);
 -      
 -              ctx->sig->sig_mr->need_inval = true;
 -              ib_update_fast_reg_key(ctx->sig->sig_mr,
 -                      ib_inc_rkey(ctx->sig->sig_mr->lkey));
 -              ctx->sig->sig_sge.lkey = ctx->sig->sig_mr->lkey;
 -
 -              if (ctx->sig->data.inv_wr.next)
 -                      first_wr = &ctx->sig->data.inv_wr;
 -              else
 -                      first_wr = &ctx->sig->data.reg_wr.wr;
 -              last_wr = &ctx->sig->data.wr.wr;
 -              break;
        case RDMA_RW_MR:
 +              /* fallthrough */
                for (i = 0; i < ctx->nr_ops; i++) {
                        rdma_rw_update_lkey(&ctx->reg[i],
                                ctx->reg[i].wr.wr.opcode !=
@@@ -599,7 -605,7 +591,7 @@@ EXPORT_SYMBOL(rdma_rw_ctx_destroy)
  
  /**
   * rdma_rw_ctx_destroy_signature - release all resources allocated by
 - *    rdma_rw_ctx_init_signature
 + *    rdma_rw_ctx_signature_init
   * @ctx:      context to release
   * @qp:               queue pair to operate on
   * @port_num: port num to which the connection is bound
@@@ -617,12 -623,16 +609,12 @@@ void rdma_rw_ctx_destroy_signature(stru
        if (WARN_ON_ONCE(ctx->type != RDMA_RW_SIG_MR))
                return;
  
 -      ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->data.mr);
 -      ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
 +      ib_mr_pool_put(qp, &qp->sig_mrs, ctx->reg->mr);
 +      kfree(ctx->reg);
  
 -      if (ctx->sig->prot.mr) {
 -              ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->prot.mr);
 +      ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
 +      if (prot_sg_cnt)
                ib_dma_unmap_sg(qp->pd->device, prot_sg, prot_sg_cnt, dir);
 -      }
 -
 -      ib_mr_pool_put(qp, &qp->sig_mrs, ctx->sig->sig_mr);
 -      kfree(ctx->sig);
  }
  EXPORT_SYMBOL(rdma_rw_ctx_destroy_signature);
  
@@@ -643,7 -653,7 +635,7 @@@ unsigned int rdma_rw_mr_factor(struct i
        unsigned int mr_pages;
  
        if (rdma_rw_can_use_mr(device, port_num))
 -              mr_pages = rdma_rw_fr_page_list_len(device);
 +              mr_pages = rdma_rw_fr_page_list_len(device, false);
        else
                mr_pages = device->attrs.max_sge_rd;
        return DIV_ROUND_UP(maxpages, mr_pages);
@@@ -669,8 -679,9 +661,8 @@@ void rdma_rw_init_qp(struct ib_device *
         * we'll need two additional MRs for the registrations and the
         * invalidation.
         */
 -      if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN)
 -              factor += 6;    /* (inv + reg) * (data + prot + sig) */
 -      else if (rdma_rw_can_use_mr(dev, attr->port_num))
 +      if (attr->create_flags & IB_QP_CREATE_INTEGRITY_EN ||
 +          rdma_rw_can_use_mr(dev, attr->port_num))
                factor += 2;    /* inv + reg */
  
        attr->cap.max_send_wr += factor * attr->cap.max_rdma_ctxs;
  int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr)
  {
        struct ib_device *dev = qp->pd->device;
 -      u32 nr_mrs = 0, nr_sig_mrs = 0;
 +      u32 nr_mrs = 0, nr_sig_mrs = 0, max_num_sg = 0;
        int ret = 0;
  
 -      if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN) {
 +      if (attr->create_flags & IB_QP_CREATE_INTEGRITY_EN) {
                nr_sig_mrs = attr->cap.max_rdma_ctxs;
 -              nr_mrs = attr->cap.max_rdma_ctxs * 2;
 +              nr_mrs = attr->cap.max_rdma_ctxs;
 +              max_num_sg = rdma_rw_fr_page_list_len(dev, true);
        } else if (rdma_rw_can_use_mr(dev, attr->port_num)) {
                nr_mrs = attr->cap.max_rdma_ctxs;
 +              max_num_sg = rdma_rw_fr_page_list_len(dev, false);
        }
  
        if (nr_mrs) {
                ret = ib_mr_pool_init(qp, &qp->rdma_mrs, nr_mrs,
                                IB_MR_TYPE_MEM_REG,
 -                              rdma_rw_fr_page_list_len(dev));
 +                              max_num_sg, 0);
                if (ret) {
                        pr_err("%s: failed to allocated %d MRs\n",
                                __func__, nr_mrs);
  
        if (nr_sig_mrs) {
                ret = ib_mr_pool_init(qp, &qp->sig_mrs, nr_sig_mrs,
 -                              IB_MR_TYPE_SIGNATURE, 2);
 +                              IB_MR_TYPE_INTEGRITY, max_num_sg, max_num_sg);
                if (ret) {
                        pr_err("%s: failed to allocated %d SIG MRs\n",
 -                              __func__, nr_mrs);
 +                              __func__, nr_sig_mrs);
                        goto out_free_rdma_mrs;
                }
        }
@@@ -174,6 -174,17 +174,17 @@@ static int uverbs_request_finish(struc
        return 0;
  }
  
+ /*
+  * When calling a destroy function during an error unwind we need to pass in
+  * the udata that is sanitized of all user arguments. Ie from the driver
+  * perspective it looks like no udata was passed.
+  */
+ struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+ {
+       attrs->driver_udata = (struct ib_udata){};
+       return &attrs->driver_udata;
+ }
  static struct ib_uverbs_completion_event_file *
  _ib_uverbs_lookup_comp_file(s32 fd, struct uverbs_attr_bundle *attrs)
  {
@@@ -441,7 -452,7 +452,7 @@@ static int ib_uverbs_alloc_pd(struct uv
        return uobj_alloc_commit(uobj, attrs);
  
  err_copy:
-       ib_dealloc_pd_user(pd, &attrs->driver_udata);
+       ib_dealloc_pd_user(pd, uverbs_get_cleared_udata(attrs));
        pd = NULL;
  err_alloc:
        kfree(pd);
@@@ -644,7 -655,7 +655,7 @@@ err_copy
        }
  
  err_dealloc_xrcd:
-       ib_dealloc_xrcd(xrcd, &attrs->driver_udata);
+       ib_dealloc_xrcd(xrcd, uverbs_get_cleared_udata(attrs));
  
  err:
        uobj_alloc_abort(&obj->uobject, attrs);
@@@ -745,9 -756,7 +756,9 @@@ static int ib_uverbs_reg_mr(struct uver
  
        mr->device  = pd->device;
        mr->pd      = pd;
 +      mr->type    = IB_MR_TYPE_USER;
        mr->dm      = NULL;
 +      mr->sig_attrs = NULL;
        mr->uobject = uobj;
        atomic_inc(&pd->usecnt);
        mr->res.type = RDMA_RESTRACK_MR;
        return uobj_alloc_commit(uobj, attrs);
  
  err_copy:
-       ib_dereg_mr_user(mr, &attrs->driver_udata);
+       ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs));
  
  err_put:
        uobj_put_obj_read(pd);
@@@ -1012,11 -1021,12 +1023,11 @@@ static struct ib_ucq_object *create_cq(
        attr.comp_vector = cmd->comp_vector;
        attr.flags = cmd->flags;
  
 -      cq = ib_dev->ops.create_cq(ib_dev, &attr, &attrs->driver_udata);
 -      if (IS_ERR(cq)) {
 -              ret = PTR_ERR(cq);
 +      cq = rdma_zalloc_drv_obj(ib_dev, ib_cq);
 +      if (!cq) {
 +              ret = -ENOMEM;
                goto err_file;
        }
 -
        cq->device        = ib_dev;
        cq->uobject       = &obj->uobject;
        cq->comp_handler  = ib_uverbs_comp_handler;
        cq->cq_context    = ev_file ? &ev_file->ev_queue : NULL;
        atomic_set(&cq->usecnt, 0);
  
 +      ret = ib_dev->ops.create_cq(cq, &attr, &attrs->driver_udata);
 +      if (ret)
 +              goto err_free;
 +
        obj->uobject.object = cq;
        memset(&resp, 0, sizeof resp);
        resp.base.cq_handle = obj->uobject.id;
        return obj;
  
  err_cb:
-       ib_destroy_cq(cq);
+       ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
 -
 +      cq = NULL;
 +err_free:
 +      kfree(cq);
  err_file:
        if (ev_file)
                ib_uverbs_release_ucq(attrs->ufile, ev_file, obj);
@@@ -1485,7 -1489,7 +1496,7 @@@ static int create_qp(struct uverbs_attr
  
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
  err_cb:
-       ib_destroy_qp(qp);
+       ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
  
  err_put:
        if (!IS_ERR(xrcd_uobj))
@@@ -1618,7 -1622,7 +1629,7 @@@ static int ib_uverbs_open_qp(struct uve
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
  
  err_destroy:
-       ib_destroy_qp(qp);
+       ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
  err_xrcd:
        uobj_put_read(xrcd_uobj);
  err_put:
@@@ -2460,7 -2464,8 +2471,8 @@@ static int ib_uverbs_create_ah(struct u
        return uobj_alloc_commit(uobj, attrs);
  
  err_copy:
-       rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
+       rdma_destroy_ah_user(ah, RDMA_DESTROY_AH_SLEEPABLE,
+                            uverbs_get_cleared_udata(attrs));
  
  err_put:
        uobj_put_obj_read(pd);
@@@ -2971,7 -2976,7 +2983,7 @@@ static int ib_uverbs_ex_create_wq(struc
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
  
  err_copy:
-       ib_destroy_wq(wq, &attrs->driver_udata);
+       ib_destroy_wq(wq, uverbs_get_cleared_udata(attrs));
  err_put_cq:
        uobj_put_obj_read(cq);
  err_put_pd:
@@@ -3471,7 -3476,7 +3483,7 @@@ static int __uverbs_create_xsrq(struct 
        return uobj_alloc_commit(&obj->uevent.uobject, attrs);
  
  err_copy:
-       ib_destroy_srq_user(srq, &attrs->driver_udata);
+       ib_destroy_srq_user(srq, uverbs_get_cleared_udata(attrs));
  
  err_free:
        kfree(srq);
@@@ -3710,6 -3715,9 +3722,6 @@@ static int ib_uverbs_ex_modify_cq(struc
   * trailing driver_data flex array. In this case the size of the base struct
   * cannot be changed.
   */
 -#define offsetof_after(_struct, _member)                                       \
 -      (offsetof(_struct, _member) + sizeof(((_struct *)NULL)->_member))
 -
  #define UAPI_DEF_WRITE_IO(req, resp)                                           \
        .write.has_resp = 1 +                                                  \
                          BUILD_BUG_ON_ZERO(offsetof(req, response) != 0) +    \
   */
  #define UAPI_DEF_WRITE_IO_EX(req, req_last_member, resp, resp_last_member)     \
        .write.has_resp = 1,                                                   \
 -      .write.req_size = offsetof_after(req, req_last_member),                \
 -      .write.resp_size = offsetof_after(resp, resp_last_member)
 +      .write.req_size = offsetofend(req, req_last_member),                   \
 +      .write.resp_size = offsetofend(resp, resp_last_member)
  
  #define UAPI_DEF_WRITE_I_EX(req, req_last_member)                              \
 -      .write.req_size = offsetof_after(req, req_last_member)
 +      .write.req_size = offsetofend(req, req_last_member)
  
  const struct uapi_definition uverbs_def_write_intf[] = {
        DECLARE_UVERBS_OBJECT(
@@@ -111,9 -111,9 +111,9 @@@ static int UVERBS_HANDLER(UVERBS_METHOD
        INIT_LIST_HEAD(&obj->comp_list);
        INIT_LIST_HEAD(&obj->async_list);
  
 -      cq = ib_dev->ops.create_cq(ib_dev, &attr, &attrs->driver_udata);
 -      if (IS_ERR(cq)) {
 -              ret = PTR_ERR(cq);
 +      cq = rdma_zalloc_drv_obj(ib_dev, ib_cq);
 +      if (!cq) {
 +              ret = -ENOMEM;
                goto err_event_file;
        }
  
        cq->comp_handler  = ib_uverbs_comp_handler;
        cq->event_handler = ib_uverbs_cq_event_handler;
        cq->cq_context    = ev_file ? &ev_file->ev_queue : NULL;
 -      obj->uobject.object = cq;
 -      obj->uobject.user_handle = user_handle;
        atomic_set(&cq->usecnt, 0);
        cq->res.type = RDMA_RESTRACK_CQ;
 +
 +      ret = ib_dev->ops.create_cq(cq, &attr, &attrs->driver_udata);
 +      if (ret)
 +              goto err_free;
 +
 +      obj->uobject.object = cq;
 +      obj->uobject.user_handle = user_handle;
        rdma_restrack_uadd(&cq->res);
  
        ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
  
        return 0;
  err_cq:
-       ib_destroy_cq(cq);
+       ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
 -
 +      cq = NULL;
 +err_free:
 +      kfree(cq);
  err_event_file:
        if (ev_file)
                uverbs_uobject_put(ev_file_uobj);
@@@ -128,7 -128,6 +128,7 @@@ static int UVERBS_HANDLER(UVERBS_METHOD
  
        mr->device  = pd->device;
        mr->pd      = pd;
 +      mr->type    = IB_MR_TYPE_DM;
        mr->dm      = dm;
        mr->uobject = uobj;
        atomic_inc(&pd->usecnt);
        return 0;
  
  err_dereg:
-       ib_dereg_mr_user(mr, &attrs->driver_udata);
+       ib_dereg_mr_user(mr, uverbs_get_cleared_udata(attrs));
  
        return ret;
  }
@@@ -3,6 -3,7 +3,6 @@@
   * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved.
   */
  
 -#include "efa.h"
  #include "efa_com.h"
  #include "efa_com_cmd.h"
  
@@@ -56,7 -57,7 +56,7 @@@ int efa_com_create_qp(struct efa_com_de
        res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx;
        res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx;
  
 -      return err;
 +      return 0;
  }
  
  int efa_com_modify_qp(struct efa_com_dev *edev,
@@@ -138,9 -139,11 +138,11 @@@ int efa_com_destroy_qp(struct efa_com_d
                               sizeof(qp_cmd),
                               (struct efa_admin_acq_entry *)&cmd_completion,
                               sizeof(cmd_completion));
-       if (err)
+       if (err) {
                ibdev_err(edev->efa_dev, "Failed to destroy qp-%u [%d]\n",
                          qp_cmd.qp_handle, err);
+               return err;
+       }
  
        return 0;
  }
@@@ -178,7 -181,7 +180,7 @@@ int efa_com_create_cq(struct efa_com_de
        result->cq_idx = cmd_completion.cq_idx;
        result->actual_depth = params->cq_depth;
  
 -      return err;
 +      return 0;
  }
  
  int efa_com_destroy_cq(struct efa_com_dev *edev,
                               (struct efa_admin_acq_entry *)&destroy_resp,
                               sizeof(destroy_resp));
  
-       if (err)
+       if (err) {
                ibdev_err(edev->efa_dev, "Failed to destroy CQ-%u [%d]\n",
                          params->cq_idx, err);
+               return err;
+       }
  
        return 0;
  }
@@@ -272,10 -277,12 +276,12 @@@ int efa_com_dereg_mr(struct efa_com_de
                               sizeof(mr_cmd),
                               (struct efa_admin_acq_entry *)&cmd_completion,
                               sizeof(cmd_completion));
-       if (err)
+       if (err) {
                ibdev_err(edev->efa_dev,
                          "Failed to de-register mr(lkey-%u) [%d]\n",
                          mr_cmd.l_key, err);
+               return err;
+       }
  
        return 0;
  }
@@@ -300,8 -307,7 +306,8 @@@ int efa_com_create_ah(struct efa_com_de
                               (struct efa_admin_acq_entry *)&cmd_completion,
                               sizeof(cmd_completion));
        if (err) {
 -              ibdev_err(edev->efa_dev, "Failed to create ah [%d]\n", err);
 +              ibdev_err(edev->efa_dev, "Failed to create ah for %pI6 [%d]\n",
 +                        ah_cmd.dest_addr, err);
                return err;
        }
  
@@@ -327,9 -333,11 +333,11 @@@ int efa_com_destroy_ah(struct efa_com_d
                               sizeof(ah_cmd),
                               (struct efa_admin_acq_entry *)&cmd_completion,
                               sizeof(cmd_completion));
-       if (err)
+       if (err) {
                ibdev_err(edev->efa_dev, "Failed to destroy ah-%d pd-%d [%d]\n",
                          ah_cmd.ah, ah_cmd.pd, err);
+               return err;
+       }
  
        return 0;
  }
@@@ -387,10 -395,12 +395,12 @@@ static int efa_com_get_feature_ex(struc
                               get_resp,
                               sizeof(*get_resp));
  
-       if (err)
+       if (err) {
                ibdev_err(edev->efa_dev,
                          "Failed to submit get_feature command %d [%d]\n",
                          feature_id, err);
+               return err;
+       }
  
        return 0;
  }
@@@ -534,10 -544,12 +544,12 @@@ static int efa_com_set_feature_ex(struc
                               (struct efa_admin_acq_entry *)set_resp,
                               sizeof(*set_resp));
  
-       if (err)
+       if (err) {
                ibdev_err(edev->efa_dev,
                          "Failed to submit set_feature command %d error: %d\n",
                          feature_id, err);
+               return err;
+       }
  
        return 0;
  }
@@@ -204,6 -204,7 +204,7 @@@ static u64 mmap_entry_insert(struct efa
                             void *obj, u64 address, u64 length, u8 mmap_flag)
  {
        struct efa_mmap_entry *entry;
+       u32 next_mmap_page;
        int err;
  
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        entry->mmap_flag = mmap_flag;
  
        xa_lock(&ucontext->mmap_xa);
+       if (check_add_overflow(ucontext->mmap_xa_page,
+                              (u32)(length >> PAGE_SHIFT),
+                              &next_mmap_page))
+               goto err_unlock;
        entry->mmap_page = ucontext->mmap_xa_page;
-       ucontext->mmap_xa_page += DIV_ROUND_UP(length, PAGE_SIZE);
+       ucontext->mmap_xa_page = next_mmap_page;
        err = __xa_insert(&ucontext->mmap_xa, entry->mmap_page, entry,
                          GFP_KERNEL);
+       if (err)
+               goto err_unlock;
        xa_unlock(&ucontext->mmap_xa);
-       if (err){
-               kfree(entry);
-               return EFA_MMAP_INVALID;
-       }
  
        ibdev_dbg(
                &dev->ibdev,
                entry->obj, entry->address, entry->length, get_mmap_key(entry));
  
        return get_mmap_key(entry);
+ err_unlock:
+       xa_unlock(&ucontext->mmap_xa);
+       kfree(entry);
+       return EFA_MMAP_INVALID;
  }
  
  int efa_query_device(struct ib_device *ibdev,
@@@ -436,6 -447,12 +447,6 @@@ void efa_dealloc_pd(struct ib_pd *ibpd
        struct efa_dev *dev = to_edev(ibpd->device);
        struct efa_pd *pd = to_epd(ibpd);
  
 -      if (udata->inlen &&
 -          !ib_is_udata_cleared(udata, 0, udata->inlen)) {
 -              ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n");
 -              return;
 -      }
 -
        ibdev_dbg(&dev->ibdev, "Dealloc pd[%d]\n", pd->pdn);
        efa_pd_dealloc(dev, pd->pdn);
  }
@@@ -453,6 -470,12 +464,6 @@@ int efa_destroy_qp(struct ib_qp *ibqp, 
        struct efa_qp *qp = to_eqp(ibqp);
        int err;
  
 -      if (udata->inlen &&
 -          !ib_is_udata_cleared(udata, 0, udata->inlen)) {
 -              ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n");
 -              return -EINVAL;
 -      }
 -
        ibdev_dbg(&dev->ibdev, "Destroy qp[%u]\n", ibqp->qp_num);
        err = efa_destroy_qp_handle(dev, qp->qp_handle);
        if (err)
@@@ -847,18 -870,31 +858,18 @@@ static int efa_destroy_cq_idx(struct ef
        return efa_com_destroy_cq(&dev->edev, &params);
  }
  
 -int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
 +void efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
  {
        struct efa_dev *dev = to_edev(ibcq->device);
        struct efa_cq *cq = to_ecq(ibcq);
 -      int err;
 -
 -      if (udata->inlen &&
 -          !ib_is_udata_cleared(udata, 0, udata->inlen)) {
 -              ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n");
 -              return -EINVAL;
 -      }
  
        ibdev_dbg(&dev->ibdev,
                  "Destroy cq[%d] virt[0x%p] freed: size[%lu], dma[%pad]\n",
                  cq->cq_idx, cq->cpu_addr, cq->size, &cq->dma_addr);
  
 -      err = efa_destroy_cq_idx(dev, cq->cq_idx);
 -      if (err)
 -              return err;
 -
 +      efa_destroy_cq_idx(dev, cq->cq_idx);
        dma_unmap_single(&dev->pdev->dev, cq->dma_addr, cq->size,
                         DMA_FROM_DEVICE);
 -
 -      kfree(cq);
 -      return 0;
  }
  
  static int cq_mmap_entries_setup(struct efa_dev *dev, struct efa_cq *cq,
        return 0;
  }
  
 -static struct ib_cq *do_create_cq(struct ib_device *ibdev, int entries,
 -                                int vector, struct ib_ucontext *ibucontext,
 -                                struct ib_udata *udata)
 +int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 +                struct ib_udata *udata)
  {
 +      struct efa_ucontext *ucontext = rdma_udata_to_drv_context(
 +              udata, struct efa_ucontext, ibucontext);
        struct efa_ibv_create_cq_resp resp = {};
        struct efa_com_create_cq_params params;
        struct efa_com_create_cq_result result;
 +      struct ib_device *ibdev = ibcq->device;
        struct efa_dev *dev = to_edev(ibdev);
        struct efa_ibv_create_cq cmd = {};
 +      struct efa_cq *cq = to_ecq(ibcq);
        bool cq_entry_inserted = false;
 -      struct efa_cq *cq;
 +      int entries = attr->cqe;
        int err;
  
        ibdev_dbg(ibdev, "create_cq entries %d\n", entries);
                goto err_out;
        }
  
 -      cq = kzalloc(sizeof(*cq), GFP_KERNEL);
 -      if (!cq) {
 -              err = -ENOMEM;
 -              goto err_out;
 -      }
 -
 -      cq->ucontext = to_eucontext(ibucontext);
 +      cq->ucontext = ucontext;
        cq->size = PAGE_ALIGN(cmd.cq_entry_size * entries * cmd.num_sub_cqs);
        cq->cpu_addr = efa_zalloc_mapped(dev, &cq->dma_addr, cq->size,
                                         DMA_FROM_DEVICE);
        if (!cq->cpu_addr) {
                err = -ENOMEM;
 -              goto err_free_cq;
 +              goto err_out;
        }
  
        params.uarn = cq->ucontext->uarn;
  
        err = cq_mmap_entries_setup(dev, cq, &resp);
        if (err) {
 -              ibdev_dbg(ibdev,
 -                        "Could not setup cq[%u] mmap entries\n", cq->cq_idx);
 +              ibdev_dbg(ibdev, "Could not setup cq[%u] mmap entries\n",
 +                        cq->cq_idx);
                goto err_destroy_cq;
        }
  
                }
        }
  
 -      ibdev_dbg(ibdev,
 -                "Created cq[%d], cq depth[%u]. dma[%pad] virt[0x%p]\n",
 +      ibdev_dbg(ibdev, "Created cq[%d], cq depth[%u]. dma[%pad] virt[0x%p]\n",
                  cq->cq_idx, result.actual_depth, &cq->dma_addr, cq->cpu_addr);
  
 -      return &cq->ibcq;
 +      return 0;
  
  err_destroy_cq:
        efa_destroy_cq_idx(dev, cq->cq_idx);
@@@ -999,9 -1039,23 +1010,9 @@@ err_free_mapped
                         DMA_FROM_DEVICE);
        if (!cq_entry_inserted)
                free_pages_exact(cq->cpu_addr, cq->size);
 -err_free_cq:
 -      kfree(cq);
  err_out:
        atomic64_inc(&dev->stats.sw_stats.create_cq_err);
 -      return ERR_PTR(err);
 -}
 -
 -struct ib_cq *efa_create_cq(struct ib_device *ibdev,
 -                          const struct ib_cq_init_attr *attr,
 -                          struct ib_udata *udata)
 -{
 -      struct efa_ucontext *ucontext = rdma_udata_to_drv_context(udata,
 -                                                                struct efa_ucontext,
 -                                                                ibucontext);
 -
 -      return do_create_cq(ibdev, attr->cqe, attr->comp_vector,
 -                          &ucontext->ibucontext, udata);
 +      return err;
  }
  
  static int umem_to_page_list(struct efa_dev *dev,
                             u8 hp_shift)
  {
        u32 pages_in_hp = BIT(hp_shift - PAGE_SHIFT);
 -      struct sg_dma_page_iter sg_iter;
 -      unsigned int page_idx = 0;
 +      struct ib_block_iter biter;
        unsigned int hp_idx = 0;
  
        ibdev_dbg(&dev->ibdev, "hp_cnt[%u], pages_in_hp[%u]\n",
                  hp_cnt, pages_in_hp);
  
 -      for_each_sg_dma_page(umem->sg_head.sgl, &sg_iter, umem->nmap, 0) {
 -              if (page_idx % pages_in_hp == 0) {
 -                      page_list[hp_idx] = sg_page_iter_dma_address(&sg_iter);
 -                      hp_idx++;
 -              }
 -
 -              page_idx++;
 -      }
 +      rdma_for_each_block(umem->sg_head.sgl, &biter, umem->nmap,
 +                          BIT(hp_shift))
 +              page_list[hp_idx++] = rdma_block_iter_dma_address(&biter);
  
        return 0;
  }
   */
  static int pbl_chunk_list_create(struct efa_dev *dev, struct pbl_context *pbl)
  {
 -      unsigned int entry, payloads_in_sg, chunk_list_size, chunk_idx, payload_idx;
        struct pbl_chunk_list *chunk_list = &pbl->phys.indirect.chunk_list;
        int page_cnt = pbl->phys.indirect.pbl_buf_size_in_pages;
        struct scatterlist *pages_sgl = pbl->phys.indirect.sgl;
 +      unsigned int chunk_list_size, chunk_idx, payload_idx;
        int sg_dma_cnt = pbl->phys.indirect.sg_dma_cnt;
        struct efa_com_ctrl_buff_info *ctrl_buf;
        u64 *cur_chunk_buf, *prev_chunk_buf;
 -      struct scatterlist *sg;
 +      struct ib_block_iter biter;
        dma_addr_t dma_addr;
        int i;
  
        chunk_idx = 0;
        payload_idx = 0;
        cur_chunk_buf = chunk_list->chunks[0].buf;
 -      for_each_sg(pages_sgl, sg, sg_dma_cnt, entry) {
 -              payloads_in_sg = sg_dma_len(sg) >> EFA_CHUNK_PAYLOAD_SHIFT;
 -              for (i = 0; i < payloads_in_sg; i++) {
 -                      cur_chunk_buf[payload_idx++] =
 -                              (sg_dma_address(sg) & ~(EFA_CHUNK_PAYLOAD_SIZE - 1)) +
 -                              (EFA_CHUNK_PAYLOAD_SIZE * i);
 -
 -                      if (payload_idx == EFA_PTRS_PER_CHUNK) {
 -                              chunk_idx++;
 -                              cur_chunk_buf = chunk_list->chunks[chunk_idx].buf;
 -                              payload_idx = 0;
 -                      }
 +      rdma_for_each_block(pages_sgl, &biter, sg_dma_cnt,
 +                          EFA_CHUNK_PAYLOAD_SIZE) {
 +              cur_chunk_buf[payload_idx++] =
 +                      rdma_block_iter_dma_address(&biter);
 +
 +              if (payload_idx == EFA_PTRS_PER_CHUNK) {
 +                      chunk_idx++;
 +                      cur_chunk_buf = chunk_list->chunks[chunk_idx].buf;
 +                      payload_idx = 0;
                }
        }
  
@@@ -1251,30 -1314,30 +1262,30 @@@ static int pbl_create(struct efa_dev *d
        int err;
  
        pbl->pbl_buf_size_in_bytes = hp_cnt * EFA_CHUNK_PAYLOAD_PTR_SIZE;
 -      pbl->pbl_buf = kzalloc(pbl->pbl_buf_size_in_bytes,
 -                             GFP_KERNEL | __GFP_NOWARN);
 -      if (pbl->pbl_buf) {
 -              pbl->physically_continuous = 1;
 +      pbl->pbl_buf = kvzalloc(pbl->pbl_buf_size_in_bytes, GFP_KERNEL);
 +      if (!pbl->pbl_buf)
 +              return -ENOMEM;
 +
 +      if (is_vmalloc_addr(pbl->pbl_buf)) {
 +              pbl->physically_continuous = 0;
                err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt,
                                        hp_shift);
                if (err)
 -                      goto err_continuous;
 -              err = pbl_continuous_initialize(dev, pbl);
 +                      goto err_free;
 +
 +              err = pbl_indirect_initialize(dev, pbl);
                if (err)
 -                      goto err_continuous;
 +                      goto err_free;
        } else {
 -              pbl->physically_continuous = 0;
 -              pbl->pbl_buf = vzalloc(pbl->pbl_buf_size_in_bytes);
 -              if (!pbl->pbl_buf)
 -                      return -ENOMEM;
 -
 +              pbl->physically_continuous = 1;
                err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt,
                                        hp_shift);
                if (err)
 -                      goto err_indirect;
 -              err = pbl_indirect_initialize(dev, pbl);
 +                      goto err_free;
 +
 +              err = pbl_continuous_initialize(dev, pbl);
                if (err)
 -                      goto err_indirect;
 +                      goto err_free;
        }
  
        ibdev_dbg(&dev->ibdev,
  
        return 0;
  
 -err_continuous:
 -      kfree(pbl->pbl_buf);
 -      return err;
 -err_indirect:
 -      vfree(pbl->pbl_buf);
 +err_free:
 +      kvfree(pbl->pbl_buf);
        return err;
  }
  
  static void pbl_destroy(struct efa_dev *dev, struct pbl_context *pbl)
  {
 -      if (pbl->physically_continuous) {
 +      if (pbl->physically_continuous)
                dma_unmap_single(&dev->pdev->dev, pbl->phys.continuous.dma_addr,
                                 pbl->pbl_buf_size_in_bytes, DMA_TO_DEVICE);
 -              kfree(pbl->pbl_buf);
 -      } else {
 +      else
                pbl_indirect_terminate(dev, pbl);
 -              vfree(pbl->pbl_buf);
 -      }
 +
 +      kvfree(pbl->pbl_buf);
  }
  
  static int efa_create_inline_pbl(struct efa_dev *dev, struct efa_mr *mr,
@@@ -1350,6 -1417,56 +1361,6 @@@ static int efa_create_pbl(struct efa_de
        return 0;
  }
  
 -static void efa_cont_pages(struct ib_umem *umem, u64 addr,
 -                         unsigned long max_page_shift,
 -                         int *count, u8 *shift, u32 *ncont)
 -{
 -      struct scatterlist *sg;
 -      u64 base = ~0, p = 0;
 -      unsigned long tmp;
 -      unsigned long m;
 -      u64 len, pfn;
 -      int i = 0;
 -      int entry;
 -
 -      addr = addr >> PAGE_SHIFT;
 -      tmp = (unsigned long)addr;
 -      m = find_first_bit(&tmp, BITS_PER_LONG);
 -      if (max_page_shift)
 -              m = min_t(unsigned long, max_page_shift - PAGE_SHIFT, m);
 -
 -      for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
 -              len = DIV_ROUND_UP(sg_dma_len(sg), PAGE_SIZE);
 -              pfn = sg_dma_address(sg) >> PAGE_SHIFT;
 -              if (base + p != pfn) {
 -                      /*
 -                       * If either the offset or the new
 -                       * base are unaligned update m
 -                       */
 -                      tmp = (unsigned long)(pfn | p);
 -                      if (!IS_ALIGNED(tmp, 1 << m))
 -                              m = find_first_bit(&tmp, BITS_PER_LONG);
 -
 -                      base = pfn;
 -                      p = 0;
 -              }
 -
 -              p += len;
 -              i += len;
 -      }
 -
 -      if (i) {
 -              m = min_t(unsigned long, ilog2(roundup_pow_of_two(i)), m);
 -              *ncont = DIV_ROUND_UP(i, (1 << m));
 -      } else {
 -              m = 0;
 -              *ncont = 0;
 -      }
 -
 -      *shift = PAGE_SHIFT + m;
 -      *count = i;
 -}
 -
  struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length,
                         u64 virt_addr, int access_flags,
                         struct ib_udata *udata)
        struct efa_dev *dev = to_edev(ibpd->device);
        struct efa_com_reg_mr_params params = {};
        struct efa_com_reg_mr_result result = {};
 -      unsigned long max_page_shift;
        struct pbl_context pbl;
 +      unsigned int pg_sz;
        struct efa_mr *mr;
        int inline_size;
 -      int npages;
        int err;
  
        if (udata->inlen &&
        params.iova = virt_addr;
        params.mr_length_in_bytes = length;
        params.permissions = access_flags & 0x1;
 -      max_page_shift = fls64(dev->dev_attr.page_size_cap);
  
 -      efa_cont_pages(mr->umem, start, max_page_shift, &npages,
 -                     &params.page_shift, &params.page_num);
 +      pg_sz = ib_umem_find_best_pgsz(mr->umem,
 +                                     dev->dev_attr.page_size_cap,
 +                                     virt_addr);
 +      if (!pg_sz) {
 +              err = -EOPNOTSUPP;
 +              ibdev_dbg(&dev->ibdev, "Failed to find a suitable page size in page_size_cap %#llx\n",
 +                        dev->dev_attr.page_size_cap);
 +              goto err_unmap;
 +      }
 +
 +      params.page_shift = __ffs(pg_sz);
 +      params.page_num = DIV_ROUND_UP(length + (start & (pg_sz - 1)),
 +                                     pg_sz);
 +
        ibdev_dbg(&dev->ibdev,
 -                "start %#llx length %#llx npages %d params.page_shift %u params.page_num %u\n",
 -                start, length, npages, params.page_shift, params.page_num);
 +                "start %#llx length %#llx params.page_shift %u params.page_num %u\n",
 +                start, length, params.page_shift, params.page_num);
  
        inline_size = ARRAY_SIZE(params.pbl.inline_pbl_array);
        if (params.page_num <= inline_size) {
@@@ -1460,6 -1567,12 +1471,6 @@@ int efa_dereg_mr(struct ib_mr *ibmr, st
        struct efa_mr *mr = to_emr(ibmr);
        int err;
  
 -      if (udata->inlen &&
 -          !ib_is_udata_cleared(udata, 0, udata->inlen)) {
 -              ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n");
 -              return -EINVAL;
 -      }
 -
        ibdev_dbg(&dev->ibdev, "Deregister mr[%d]\n", ibmr->lkey);
  
        if (mr->umem) {
                err = efa_com_dereg_mr(&dev->edev, &params);
                if (err)
                        return err;
 -              ib_umem_release(mr->umem);
        }
 +      ib_umem_release(mr->umem);
  
        kfree(mr);
  
@@@ -1594,15 -1707,13 +1605,15 @@@ static int __efa_mmap(struct efa_dev *d
                err = -EINVAL;
        }
  
 -      if (err)
 +      if (err) {
                ibdev_dbg(
                        &dev->ibdev,
                        "Couldn't mmap address[%#llx] length[%#llx] mmap_flag[%d] err[%d]\n",
                        entry->address, length, entry->mmap_flag, err);
 +              return err;
 +      }
  
 -      return err;
 +      return 0;
  }
  
  int efa_mmap(struct ib_ucontext *ibucontext,
                ibdev_dbg(&dev->ibdev, "Mapping executable pages is not permitted\n");
                return -EPERM;
        }
-       vma->vm_flags &= ~VM_MAYEXEC;
  
        return __efa_mmap(dev, ucontext, vma, key, length);
  }
@@@ -952,6 -952,22 +952,22 @@@ void sc_disable(struct send_context *sc
                }
        }
        spin_unlock(&sc->release_lock);
+       write_seqlock(&sc->waitlock);
+       while (!list_empty(&sc->piowait)) {
+               struct iowait *wait;
+               struct rvt_qp *qp;
+               struct hfi1_qp_priv *priv;
+               wait = list_first_entry(&sc->piowait, struct iowait, list);
+               qp = iowait_to_qp(wait);
+               priv = qp->priv;
+               list_del_init(&priv->s_iowait.list);
+               priv->s_iowait.lock = NULL;
+               hfi1_qp_wakeup(qp, RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
+       }
+       write_sequnlock(&sc->waitlock);
        spin_unlock_irq(&sc->alloc_lock);
  }
  
@@@ -1427,7 -1443,8 +1443,8 @@@ void sc_stop(struct send_context *sc, i
   * @cb: optional callback to call when the buffer is finished sending
   * @arg: argument for cb
   *
-  * Return a pointer to a PIO buffer if successful, NULL if not enough room.
+  * Return a pointer to a PIO buffer, NULL if not enough room, -ECOMM
+  * when link is down.
   */
  struct pio_buf *sc_buffer_alloc(struct send_context *sc, u32 dw_len,
                                pio_release_cb cb, void *arg)
        spin_lock_irqsave(&sc->alloc_lock, flags);
        if (!(sc->flags & SCF_ENABLED)) {
                spin_unlock_irqrestore(&sc->alloc_lock, flags);
-               goto done;
+               return ERR_PTR(-ECOMM);
        }
  
  retry:
@@@ -1577,8 -1594,9 +1594,8 @@@ void hfi1_sc_wantpiobuf_intr(struct sen
        else
                sc_del_credit_return_intr(sc);
        trace_hfi1_wantpiointr(sc, needint, sc->credit_ctrl);
 -      if (needint) {
 +      if (needint)
                sc_return_credits(sc);
 -      }
  }
  
  /**
@@@ -1432,7 -1432,7 +1432,7 @@@ void hfi1_send_rc_ack(struct hfi1_packe
        pbc = create_pbc(ppd, pbc_flags, qp->srate_mbps,
                         sc_to_vlt(ppd->dd, sc5), plen);
        pbuf = sc_buffer_alloc(rcd->sc, plen, NULL, NULL);
-       if (!pbuf) {
+       if (IS_ERR_OR_NULL(pbuf)) {
                /*
                 * We have no room to send at the moment.  Pass
                 * responsibility for sending the ACK to the send engine
@@@ -1701,6 -1701,36 +1701,36 @@@ static void reset_sending_psn(struct rv
        }
  }
  
+ /**
+  * hfi1_rc_verbs_aborted - handle abort status
+  * @qp: the QP
+  * @opah: the opa header
+  *
+  * This code modifies both ACK bit in BTH[2]
+  * and the s_flags to go into send one mode.
+  *
+  * This serves to throttle the send engine to only
+  * send a single packet in the likely case the
+  * a link has gone down.
+  */
+ void hfi1_rc_verbs_aborted(struct rvt_qp *qp, struct hfi1_opa_header *opah)
+ {
+       struct ib_other_headers *ohdr = hfi1_get_rc_ohdr(opah);
+       u8 opcode = ib_bth_get_opcode(ohdr);
+       u32 psn;
+       /* ignore responses */
+       if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
+            opcode <= OP(ATOMIC_ACKNOWLEDGE)) ||
+           opcode == TID_OP(READ_RESP) ||
+           opcode == TID_OP(WRITE_RESP))
+               return;
+       psn = ib_bth_get_psn(ohdr) | IB_BTH_REQ_ACK;
+       ohdr->bth[2] = cpu_to_be32(psn);
+       qp->s_flags |= RVT_S_SEND_ONE;
+ }
  /*
   * This should be called with the QP s_lock held and interrupts disabled.
   */
@@@ -1709,8 -1739,6 +1739,6 @@@ void hfi1_rc_send_complete(struct rvt_q
        struct ib_other_headers *ohdr;
        struct hfi1_qp_priv *priv = qp->priv;
        struct rvt_swqe *wqe;
-       struct ib_header *hdr = NULL;
-       struct hfi1_16b_header *hdr_16b = NULL;
        u32 opcode, head, tail;
        u32 psn;
        struct tid_rdma_request *req;
        if (!(ib_rvt_state_ops[qp->state] & RVT_SEND_OR_FLUSH_OR_RECV_OK))
                return;
  
-       /* Find out where the BTH is */
-       if (priv->hdr_type == HFI1_PKT_TYPE_9B) {
-               hdr = &opah->ibh;
-               if (ib_get_lnh(hdr) == HFI1_LRH_BTH)
-                       ohdr = &hdr->u.oth;
-               else
-                       ohdr = &hdr->u.l.oth;
-       } else {
-               u8 l4;
-               hdr_16b = &opah->opah;
-               l4  = hfi1_16B_get_l4(hdr_16b);
-               if (l4 == OPA_16B_L4_IB_LOCAL)
-                       ohdr = &hdr_16b->u.oth;
-               else
-                       ohdr = &hdr_16b->u.l.oth;
-       }
+       ohdr = hfi1_get_rc_ohdr(opah);
        opcode = ib_bth_get_opcode(ohdr);
        if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
             opcode <= OP(ATOMIC_ACKNOWLEDGE)) ||
        }
  
        while (qp->s_last != qp->s_acked) {
 -              u32 s_last;
 -
                wqe = rvt_get_swqe_ptr(qp, qp->s_last);
                if (cmp_psn(wqe->lpsn, qp->s_sending_psn) >= 0 &&
                    cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)
                        break;
                trdma_clean_swqe(qp, wqe);
                rvt_qp_wqe_unreserve(qp, wqe);
 -              s_last = qp->s_last;
 -              trace_hfi1_qp_send_completion(qp, wqe, s_last);
 -              if (++s_last >= qp->s_size)
 -                      s_last = 0;
 -              qp->s_last = s_last;
 -              /* see post_send() */
 -              barrier();
 -              rvt_put_qp_swqe(qp, wqe);
 -              rvt_qp_swqe_complete(qp,
 +              trace_hfi1_qp_send_completion(qp, wqe, qp->s_last);
 +              rvt_qp_complete_swqe(qp,
                                     wqe,
                                     ib_hfi1_wc_opcode[wqe->wr.opcode],
                                     IB_WC_SUCCESS);
@@@ -1870,10 -1890,19 +1881,10 @@@ struct rvt_swqe *do_rc_completion(struc
        trace_hfi1_rc_completion(qp, wqe->lpsn);
        if (cmp_psn(wqe->lpsn, qp->s_sending_psn) < 0 ||
            cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) {
 -              u32 s_last;
 -
                trdma_clean_swqe(qp, wqe);
 -              rvt_put_qp_swqe(qp, wqe);
                rvt_qp_wqe_unreserve(qp, wqe);
 -              s_last = qp->s_last;
 -              trace_hfi1_qp_send_completion(qp, wqe, s_last);
 -              if (++s_last >= qp->s_size)
 -                      s_last = 0;
 -              qp->s_last = s_last;
 -              /* see post_send() */
 -              barrier();
 -              rvt_qp_swqe_complete(qp,
 +              trace_hfi1_qp_send_completion(qp, wqe, qp->s_last);
 +              rvt_qp_complete_swqe(qp,
                                     wqe,
                                     ib_hfi1_wc_opcode[wqe->wr.opcode],
                                     IB_WC_SUCCESS);
@@@ -312,9 -312,7 +312,7 @@@ static struct hfi1_ctxtdata *qp_to_rcd(
        if (qp->ibqp.qp_num == 0)
                ctxt = 0;
        else
-               ctxt = ((qp->ibqp.qp_num >> dd->qos_shift) %
-                       (dd->n_krcv_queues - 1)) + 1;
+               ctxt = hfi1_get_qp_map(dd, qp->ibqp.qp_num >> dd->qos_shift);
        return dd->rcd[ctxt];
  }
  
@@@ -477,7 -475,7 +475,7 @@@ static struct rvt_qp *first_qp(struct h
   * Must hold the qp s_lock and the exp_lock.
   *
   * Return:
 - * false if either of the conditions below are statisfied:
 + * false if either of the conditions below are satisfied:
   * 1. The list is empty or
   * 2. The indicated qp is at the head of the list and the
   *    HFI1_S_WAIT_TID_SPACE bit is set in qp->s_flags.
@@@ -2026,6 -2024,7 +2024,6 @@@ static int tid_rdma_rcv_error(struct hf
        trace_hfi1_tid_req_rcv_err(qp, 0, e->opcode, e->psn, e->lpsn, req);
        if (e->opcode == TID_OP(READ_REQ)) {
                struct ib_reth *reth;
 -              u32 offset;
                u32 len;
                u32 rkey;
                u64 vaddr;
                 * The requester always restarts from the start of the original
                 * request.
                 */
 -              offset = delta_psn(psn, e->psn) * qp->pmtu;
                len = be32_to_cpu(reth->length);
                if (psn != e->psn || len != req->total_len)
                        goto unlock;
@@@ -4550,7 -4550,7 +4548,7 @@@ void hfi1_rc_rcv_tid_rdma_ack(struct hf
        struct rvt_swqe *wqe;
        struct tid_rdma_request *req;
        struct tid_rdma_flow *flow;
 -      u32 aeth, psn, req_psn, ack_psn, fspsn, resync_psn, ack_kpsn;
 +      u32 aeth, psn, req_psn, ack_psn, resync_psn, ack_kpsn;
        unsigned long flags;
        u16 fidx;
  
@@@ -4754,6 -4754,7 +4752,6 @@@ done
                        IB_AETH_CREDIT_MASK) {
                case 0: /* PSN sequence error */
                        flow = &req->flows[req->acked_tail];
 -                      fspsn = full_flow_psn(flow, flow->flow_state.spsn);
                        trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail,
                                                        flow);
                        req->r_ack_psn = mask_psn(be32_to_cpu(ohdr->bth[2]));
@@@ -638,6 -638,8 +638,8 @@@ static void verbs_sdma_complete
                struct hfi1_opa_header *hdr;
  
                hdr = &tx->phdr.hdr;
+               if (unlikely(status == SDMA_TXREQ_S_ABORTED))
+                       hfi1_rc_verbs_aborted(qp, hdr);
                hfi1_rc_send_complete(qp, hdr);
        }
        spin_unlock(&qp->s_lock);
@@@ -1037,10 -1039,10 +1039,10 @@@ int hfi1_verbs_send_pio(struct rvt_qp *
        if (cb)
                iowait_pio_inc(&priv->s_iowait);
        pbuf = sc_buffer_alloc(sc, plen, cb, qp);
-       if (unlikely(!pbuf)) {
+       if (unlikely(IS_ERR_OR_NULL(pbuf))) {
                if (cb)
                        verbs_pio_complete(qp, 0);
-               if (ppd->host_link_state != HLS_UP_ACTIVE) {
+               if (IS_ERR(pbuf)) {
                        /*
                         * If we have filled the PIO buffers to capacity and are
                         * not in an active state this request is not going to
                               &ps->s_txreq->phdr.hdr, ib_is_sc5(sc5));
  
  pio_bail:
+       spin_lock_irqsave(&qp->s_lock, flags);
        if (qp->s_wqe) {
-               spin_lock_irqsave(&qp->s_lock, flags);
                rvt_send_complete(qp, qp->s_wqe, wc_status);
-               spin_unlock_irqrestore(&qp->s_lock, flags);
        } else if (qp->ibqp.qp_type == IB_QPT_RC) {
-               spin_lock_irqsave(&qp->s_lock, flags);
+               if (unlikely(wc_status == IB_WC_GENERAL_ERR))
+                       hfi1_rc_verbs_aborted(qp, &ps->s_txreq->phdr.hdr);
                hfi1_rc_send_complete(qp, &ps->s_txreq->phdr.hdr);
-               spin_unlock_irqrestore(&qp->s_lock, flags);
        }
+       spin_unlock_irqrestore(&qp->s_lock, flags);
  
        ret = 0;
  
@@@ -1356,8 -1358,6 +1358,6 @@@ static void hfi1_fill_device_attr(struc
        rdi->dparms.props.max_cq = hfi1_max_cqs;
        rdi->dparms.props.max_ah = hfi1_max_ahs;
        rdi->dparms.props.max_cqe = hfi1_max_cqes;
-       rdi->dparms.props.max_mr = rdi->lkey_table.max;
-       rdi->dparms.props.max_fmr = rdi->lkey_table.max;
        rdi->dparms.props.max_map_per_fmr = 32767;
        rdi->dparms.props.max_pd = hfi1_max_pds;
        rdi->dparms.props.max_qp_rd_atom = HFI1_MAX_RDMA_ATOMIC;
@@@ -1779,9 -1779,6 +1779,9 @@@ static int get_hw_stats(struct ib_devic
  }
  
  static const struct ib_device_ops hfi1_dev_ops = {
 +      .owner = THIS_MODULE,
 +      .driver_id = RDMA_DRIVER_HFI1,
 +
        .alloc_hw_stats = alloc_hw_stats,
        .alloc_rdma_netdev = hfi1_vnic_alloc_rn,
        .get_dev_fw_str = hfi1_get_dev_fw_str,
@@@ -1832,6 -1829,7 +1832,6 @@@ int hfi1_register_ib_device(struct hfi1
         */
        if (!ib_hfi1_sys_image_guid)
                ib_hfi1_sys_image_guid = ibdev->node_guid;
 -      ibdev->owner = THIS_MODULE;
        ibdev->phys_port_cnt = dd->num_pports;
        ibdev->dev.parent = &dd->pcidev->dev;
  
        rdma_set_device_sysfs_group(&dd->verbs_dev.rdi.ibdev,
                                    &ib_hfi1_attr_group);
  
 -      ret = rvt_register_device(&dd->verbs_dev.rdi, RDMA_DRIVER_HFI1);
 +      ret = rvt_register_device(&dd->verbs_dev.rdi);
        if (ret)
                goto err_verbs_txreq;
  
@@@ -1,3 -1,4 +1,4 @@@
+ # SPDX-License-Identifier: GPL-2.0-only
  config INFINIBAND_HNS
        tristate "HNS RoCE Driver"
        depends on NET_VENDOR_HISILICON
@@@ -7,24 -8,25 +8,24 @@@
          is used in Hisilicon Hip06 and more further ICT SoC based on
          platform device.
  
 -        To compile this driver as a module, choose M here: the module
 -        will be called hns-roce.
 +        To compile HIP06 or HIP08 driver as module, choose M here.
  
  config INFINIBAND_HNS_HIP06
 -      tristate "Hisilicon Hip06 Family RoCE support"
 +      bool "Hisilicon Hip06 Family RoCE support"
        depends on INFINIBAND_HNS && HNS && HNS_DSAF && HNS_ENET
        ---help---
          RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip06 and
          Hip07 SoC. These RoCE engines are platform devices.
  
 -        To compile this driver as a module, choose M here: the module
 -        will be called hns-roce-hw-v1.
 +        To compile this driver, choose Y here: if INFINIBAND_HNS is m, this
 +        module will be called hns-roce-hw-v1
  
  config INFINIBAND_HNS_HIP08
 -      tristate "Hisilicon Hip08 Family RoCE support"
 +      bool "Hisilicon Hip08 Family RoCE support"
        depends on INFINIBAND_HNS && PCI && HNS3
        ---help---
          RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip08 SoC.
          The RoCE engine is a PCI device.
  
 -        To compile this driver as a module, choose M here: the module
 -        will be called hns-roce-hw-v2.
 +        To compile this driver, choose Y here: if INFINIBAND_HNS is m, this
 +        module will be called hns-roce-hw-v2.
@@@ -1,19 -1,15 +1,20 @@@
+ # SPDX-License-Identifier: GPL-2.0-only
  #
  # Makefile for the Hisilicon RoCE drivers.
  #
  
  ccflags-y :=  -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
  
 -obj-$(CONFIG_INFINIBAND_HNS) += hns-roce.o
  hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
        hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
        hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o
 -obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o
 +
 +ifdef CONFIG_INFINIBAND_HNS_HIP06
  hns-roce-hw-v1-objs := hns_roce_hw_v1.o
 -obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
 -hns-roce-hw-v2-objs := hns_roce_hw_v2.o hns_roce_hw_v2_dfx.o
 +obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v1.o $(hns-roce-objs)
 +endif
 +
 +ifdef CONFIG_INFINIBAND_HNS_HIP08
 +hns-roce-hw-v2-objs := hns_roce_hw_v2.o hns_roce_hw_v2_dfx.o $(hns-roce-objs)
 +obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v2.o
 +endif
@@@ -717,7 -717,7 +717,7 @@@ static int hns_roce_v1_rsv_lp_qp(struc
        union ib_gid dgid;
        u64 subnet_prefix;
        int attr_mask = 0;
 -      int ret = -ENOMEM;
 +      int ret;
        int i, j;
        u8 queue_en[HNS_ROCE_V1_RESV_QP] = { 0 };
        u8 phy_port;
        /* Reserved cq for loop qp */
        cq_init_attr.cqe                = HNS_ROCE_MIN_WQE_NUM * 2;
        cq_init_attr.comp_vector        = 0;
 -      cq = hns_roce_ib_create_cq(&hr_dev->ib_dev, &cq_init_attr, NULL);
 -      if (IS_ERR(cq)) {
 -              dev_err(dev, "Create cq for reserved loop qp failed!");
 +
 +      ibdev = &hr_dev->ib_dev;
 +      cq = rdma_zalloc_drv_obj(ibdev, ib_cq);
 +      if (!cq)
                return -ENOMEM;
 +
 +      ret = hns_roce_ib_create_cq(cq, &cq_init_attr, NULL);
 +      if (ret) {
 +              dev_err(dev, "Create cq for reserved loop qp failed!");
 +              goto alloc_cq_failed;
        }
        free_mr->mr_free_cq = to_hr_cq(cq);
        free_mr->mr_free_cq->ib_cq.device               = &hr_dev->ib_dev;
        free_mr->mr_free_cq->ib_cq.cq_context           = NULL;
        atomic_set(&free_mr->mr_free_cq->ib_cq.usecnt, 0);
  
 -      ibdev = &hr_dev->ib_dev;
        pd = rdma_zalloc_drv_obj(ibdev, ib_pd);
        if (!pd)
                goto alloc_mem_failed;
                attr.dest_qp_num        = hr_qp->qpn;
                memcpy(rdma_ah_retrieve_dmac(&attr.ah_attr),
                       hr_dev->dev_addr[port],
 -                     MAC_ADDR_OCTET_NUM);
 +                     ETH_ALEN);
  
                memcpy(&dgid.raw, &subnet_prefix, sizeof(u64));
                memcpy(&dgid.raw[8], hr_dev->dev_addr[port], 3);
@@@ -870,9 -865,9 +870,9 @@@ alloc_pd_failed
        kfree(pd);
  
  alloc_mem_failed:
 -      if (hns_roce_ib_destroy_cq(cq, NULL))
 -              dev_err(dev, "Destroy cq for create_lp_qp failed!\n");
 -
 +      hns_roce_ib_destroy_cq(cq, NULL);
 +alloc_cq_failed:
 +      kfree(cq);
        return ret;
  }
  
@@@ -899,9 -894,12 +899,10 @@@ static void hns_roce_v1_release_lp_qp(s
                                i, ret);
        }
  
 -      ret = hns_roce_ib_destroy_cq(&free_mr->mr_free_cq->ib_cq, NULL);
 -      if (ret)
 -              dev_err(dev, "Destroy cq for mr_free failed(%d)!\n", ret);
 -
 +      hns_roce_ib_destroy_cq(&free_mr->mr_free_cq->ib_cq, NULL);
 +      kfree(&free_mr->mr_free_cq->ib_cq);
        hns_roce_dealloc_pd(&free_mr->mr_free_pd->ibpd, NULL);
+       kfree(&free_mr->mr_free_pd->ibpd);
  }
  
  static int hns_roce_db_init(struct hns_roce_dev *hr_dev)
@@@ -968,7 -966,8 +969,7 @@@ static int hns_roce_v1_recreate_lp_qp(s
        struct hns_roce_free_mr *free_mr;
        struct hns_roce_v1_priv *priv;
        struct completion comp;
 -      unsigned long end =
 -        msecs_to_jiffies(HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS) + jiffies;
 +      unsigned long end = HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS;
  
        priv = (struct hns_roce_v1_priv *)hr_dev->priv;
        free_mr = &priv->free_mr;
  
        queue_work(free_mr->free_mr_wq, &(lp_qp_work->work));
  
 -      while (time_before_eq(jiffies, end)) {
 +      while (end) {
                if (try_wait_for_completion(&comp))
                        return 0;
                msleep(HNS_ROCE_V1_RECREATE_LP_QP_WAIT_VALUE);
 +              end -= HNS_ROCE_V1_RECREATE_LP_QP_WAIT_VALUE;
        }
  
        lp_qp_work->comp_flag = 0;
@@@ -1106,7 -1104,8 +1107,7 @@@ static int hns_roce_v1_dereg_mr(struct 
        struct hns_roce_free_mr *free_mr;
        struct hns_roce_v1_priv *priv;
        struct completion comp;
 -      unsigned long end =
 -              msecs_to_jiffies(HNS_ROCE_V1_FREE_MR_TIMEOUT_MSECS) + jiffies;
 +      unsigned long end = HNS_ROCE_V1_FREE_MR_TIMEOUT_MSECS;
        unsigned long start = jiffies;
        int npages;
        int ret = 0;
  
        queue_work(free_mr->free_mr_wq, &(mr_work->work));
  
 -      while (time_before_eq(jiffies, end)) {
 +      while (end) {
                if (try_wait_for_completion(&comp))
                        goto free_mr;
                msleep(HNS_ROCE_V1_FREE_MR_WAIT_VALUE);
 +              end -= HNS_ROCE_V1_FREE_MR_WAIT_VALUE;
        }
  
        mr_work->comp_flag = 0;
@@@ -1163,7 -1161,8 +1164,7 @@@ free_mr
        hns_roce_bitmap_free(&hr_dev->mr_table.mtpt_bitmap,
                             key_to_hw_index(mr->key), 0);
  
 -      if (mr->umem)
 -              ib_umem_release(mr->umem);
 +      ib_umem_release(mr->umem);
  
        kfree(mr);
  
@@@ -1743,14 -1742,11 +1744,14 @@@ static int hns_roce_v1_set_gid(struct h
                               int gid_index, const union ib_gid *gid,
                               const struct ib_gid_attr *attr)
  {
 +      unsigned long flags;
        u32 *p = NULL;
        u8 gid_idx = 0;
  
        gid_idx = hns_get_gid_index(hr_dev, port, gid_index);
  
 +      spin_lock_irqsave(&hr_dev->iboe.lock, flags);
 +
        p = (u32 *)&gid->raw[0];
        roce_raw_write(*p, hr_dev->reg_base + ROCEE_PORT_GID_L_0_REG +
                       (HNS_ROCE_V1_GID_NUM * gid_idx));
        roce_raw_write(*p, hr_dev->reg_base + ROCEE_PORT_GID_H_0_REG +
                       (HNS_ROCE_V1_GID_NUM * gid_idx));
  
 +      spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
 +
        return 0;
  }
  
@@@ -2464,10 -2458,10 +2465,10 @@@ static int hns_roce_v1_clear_hem(struc
  
        bt_cmd = hr_dev->reg_base + ROCEE_BT_CMD_H_REG;
  
 -      end = msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS) + jiffies;
 +      end = HW_SYNC_TIMEOUT_MSECS;
        while (1) {
                if (readl(bt_cmd) >> BT_CMD_SYNC_SHIFT) {
 -                      if (!(time_before(jiffies, end))) {
 +                      if (!end) {
                                dev_err(dev, "Write bt_cmd err,hw_sync is not zero.\n");
                                spin_unlock_irqrestore(&hr_dev->bt_cmd_lock,
                                        flags);
                } else {
                        break;
                }
 -              msleep(HW_SYNC_SLEEP_TIME_INTERVAL);
 +              mdelay(HW_SYNC_SLEEP_TIME_INTERVAL);
 +              end -= HW_SYNC_SLEEP_TIME_INTERVAL;
        }
  
        bt_cmd_val[0] = (__le32)bt_ba;
@@@ -3640,8 -3633,9 +3641,8 @@@ int hns_roce_v1_destroy_qp(struct ib_q
  
        hns_roce_mtt_cleanup(hr_dev, &hr_qp->mtt);
  
 -      if (udata)
 -              ib_umem_release(hr_qp->umem);
 -      else {
 +      ib_umem_release(hr_qp->umem);
 +      if (!udata) {
                kfree(hr_qp->sq.wrid);
                kfree(hr_qp->rq.wrid);
  
        return 0;
  }
  
 -static int hns_roce_v1_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
 +static void hns_roce_v1_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
  {
        struct hns_roce_dev *hr_dev = to_hr_dev(ibcq->device);
        struct hns_roce_cq *hr_cq = to_hr_cq(ibcq);
        u32 cqe_cnt_cur;
        u32 cq_buf_size;
        int wait_time = 0;
 -      int ret = 0;
  
        hns_roce_free_cq(hr_dev, hr_cq);
  
                if (wait_time > HNS_ROCE_MAX_FREE_CQ_WAIT_CNT) {
                        dev_warn(dev, "Destroy cq 0x%lx timeout!\n",
                                hr_cq->cqn);
 -                      ret = -ETIMEDOUT;
                        break;
                }
                wait_time++;
  
        hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
  
 -      if (ibcq->uobject)
 -              ib_umem_release(hr_cq->umem);
 -      else {
 +      ib_umem_release(hr_cq->umem);
 +      if (!udata) {
                /* Free the buff of stored cq */
                cq_buf_size = (ibcq->cqe + 1) * hr_dev->caps.cq_entry_sz;
                hns_roce_buf_free(hr_dev, cq_buf_size, &hr_cq->hr_buf.hr_buf);
        }
 -
 -      kfree(hr_cq);
 -
 -      return ret;
  }
  
  static void set_eq_cons_index_v1(struct hns_roce_eq *eq, int req_not)
@@@ -60,7 -60,7 +60,7 @@@ mlx5_ib_vport_rep_load(struct mlx5_core
        if (!__mlx5_ib_add(ibdev, profile))
                return -EINVAL;
  
 -      rep->rep_if[REP_IB].priv = ibdev;
 +      rep->rep_data[REP_IB].priv = ibdev;
  
        return 0;
  }
@@@ -70,13 -70,13 +70,13 @@@ mlx5_ib_vport_rep_unload(struct mlx5_es
  {
        struct mlx5_ib_dev *dev;
  
 -      if (!rep->rep_if[REP_IB].priv ||
 +      if (!rep->rep_data[REP_IB].priv ||
            rep->vport != MLX5_VPORT_UPLINK)
                return;
  
        dev = mlx5_ib_rep_to_dev(rep);
        __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
 -      rep->rep_if[REP_IB].priv = NULL;
 +      rep->rep_data[REP_IB].priv = NULL;
  }
  
  static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
        return mlx5_ib_rep_to_dev(rep);
  }
  
 +static const struct mlx5_eswitch_rep_ops rep_ops = {
 +      .load = mlx5_ib_vport_rep_load,
 +      .unload = mlx5_ib_vport_rep_unload,
 +      .get_proto_dev = mlx5_ib_vport_get_proto_dev,
 +};
 +
  void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev)
  {
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
 -      struct mlx5_eswitch_rep_if rep_if = {};
 -
 -      rep_if.load = mlx5_ib_vport_rep_load;
 -      rep_if.unload = mlx5_ib_vport_rep_unload;
 -      rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
  
 -      mlx5_eswitch_register_vport_reps(esw, &rep_if, REP_IB);
 +      mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
  }
  
  void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev)
@@@ -110,15 -109,15 +110,15 @@@ u8 mlx5_ib_eswitch_mode(struct mlx5_esw
  }
  
  struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
-                                         int vport_index)
+                                         u16 vport_num)
  {
-       return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_IB);
+       return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_IB);
  }
  
  struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
-                                         int vport_index)
+                                         u16 vport_num)
  {
-       return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_ETH);
+       return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_ETH);
  }
  
  struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
        return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB);
  }
  
- struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, int vport)
+ struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
+                                          u16 vport_num)
  {
-       return mlx5_eswitch_vport_rep(esw, vport);
+       return mlx5_eswitch_vport_rep(esw, vport_num);
  }
  
  struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
@@@ -14,17 -14,17 +14,17 @@@ extern const struct mlx5_ib_profile upl
  
  u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw);
  struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
-                                         int vport_index);
+                                         u16 vport_num);
  struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw);
  struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
-                                          int vport_index);
+                                          u16 vport_num);
  void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev);
  void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev);
  struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
                                                   struct mlx5_ib_sq *sq,
                                                   u16 port);
  struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
-                                         int vport_index);
+                                         u16 vport_num);
  #else /* CONFIG_MLX5_ESWITCH */
  static inline u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
  {
@@@ -33,7 -33,7 +33,7 @@@
  
  static inline
  struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
-                                         int vport_index)
+                                         u16 vport_num)
  {
        return NULL;
  }
@@@ -46,7 -46,7 +46,7 @@@ struct mlx5_ib_dev *mlx5_ib_get_uplink_
  
  static inline
  struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
-                                          int vport_index)
+                                          u16 vport_num)
  {
        return NULL;
  }
@@@ -63,7 -63,7 +63,7 @@@ struct mlx5_flow_handle *create_flow_ru
  
  static inline
  struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
-                                         int vport_index)
+                                         u16 vport_num)
  {
        return NULL;
  }
@@@ -72,6 -72,6 +72,6 @@@
  static inline
  struct mlx5_ib_dev *mlx5_ib_rep_to_dev(struct mlx5_eswitch_rep *rep)
  {
 -      return (struct mlx5_ib_dev *)rep->rep_if[REP_IB].priv;
 +      return rep->rep_data[REP_IB].priv;
  }
  #endif /* __MLX5_IB_REP_H__ */
@@@ -52,7 -52,6 +52,7 @@@
  #include <linux/mlx5/port.h>
  #include <linux/mlx5/vport.h>
  #include <linux/mlx5/fs.h>
 +#include <linux/mlx5/eswitch.h>
  #include <linux/list.h>
  #include <rdma/ib_smi.h>
  #include <rdma/ib_umem.h>
@@@ -889,7 -888,7 +889,7 @@@ static int mlx5_ib_query_device(struct 
        }
        props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
        if (MLX5_CAP_GEN(mdev, sho)) {
 -              props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER;
 +              props->device_cap_flags |= IB_DEVICE_INTEGRITY_HANDOVER;
                /* At this stage no support for signature handover */
                props->sig_prot_cap = IB_PROT_T10DIF_TYPE_1 |
                                      IB_PROT_T10DIF_TYPE_2 |
        props->max_srq_sge         = max_rq_sg - 1;
        props->max_fast_reg_page_list_len =
                1 << MLX5_CAP_GEN(mdev, log_max_klm_list_size);
 +      props->max_pi_fast_reg_page_list_len =
 +              props->max_fast_reg_page_list_len / 2;
        get_atomic_caps_qp(dev, props);
        props->masked_atomic_cap   = IB_ATOMIC_NONE;
        props->max_mcast_grp       = 1 << MLX5_CAP_GEN(mdev, log_max_mcg);
@@@ -2347,7 -2344,7 +2347,7 @@@ static int handle_alloc_dm_sw_icm(struc
        /* Allocation size must a multiple of the basic block size
         * and a power of 2.
         */
-       act_size = roundup(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dm_db->dev));
+       act_size = round_up(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dm_db->dev));
        act_size = roundup_pow_of_two(act_size);
  
        dm->size = act_size;
@@@ -3255,14 -3252,11 +3255,14 @@@ static struct mlx5_ib_flow_prio *get_fl
        int max_table_size;
        int num_entries;
        int num_groups;
 +      bool esw_encap;
        u32 flags = 0;
        int priority;
  
        max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
                                                       log_max_ft_size));
 +      esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) !=
 +              DEVLINK_ESWITCH_ENCAP_MODE_NONE;
        if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
                enum mlx5_flow_namespace_type fn_type;
  
                if (ft_type == MLX5_IB_FT_RX) {
                        fn_type = MLX5_FLOW_NAMESPACE_BYPASS;
                        prio = &dev->flow_db->prios[priority];
 -                      if (!dev->is_rep &&
 +                      if (!dev->is_rep && !esw_encap &&
                            MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap))
                                flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
 -                      if (!dev->is_rep &&
 +                      if (!dev->is_rep && !esw_encap &&
                            MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
                                        reformat_l3_tunnel_to_l2))
                                flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
                                                              log_max_ft_size));
                        fn_type = MLX5_FLOW_NAMESPACE_EGRESS;
                        prio = &dev->flow_db->egress_prios[priority];
 -                      if (!dev->is_rep &&
 +                      if (!dev->is_rep && !esw_encap &&
                            MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat))
                                flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
                }
@@@ -3898,7 -3892,6 +3898,7 @@@ _get_flow_table(struct mlx5_ib_dev *dev
        struct mlx5_flow_namespace *ns = NULL;
        struct mlx5_ib_flow_prio *prio = NULL;
        int max_table_size = 0;
 +      bool esw_encap;
        u32 flags = 0;
        int priority;
  
        else
                priority = ib_prio_to_core_prio(fs_matcher->priority, false);
  
 +      esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) !=
 +              DEVLINK_ESWITCH_ENCAP_MODE_NONE;
        if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) {
                max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
                                        log_max_ft_size));
 -              if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap))
 +              if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap) && !esw_encap)
                        flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
                if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
 -                                            reformat_l3_tunnel_to_l2))
 +                                            reformat_l3_tunnel_to_l2) &&
 +                  !esw_encap)
                        flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
        } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS) {
                max_table_size = BIT(
                        MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, log_max_ft_size));
 -              if (MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat))
 +              if (MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat) && !esw_encap)
                        flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
        } else if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB) {
                max_table_size = BIT(
                        MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, log_max_ft_size));
 +              if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, decap) && esw_encap)
 +                      flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
 +              if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, reformat_l3_tunnel_to_l2) &&
 +                  esw_encap)
 +                      flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
                priority = FDB_BYPASS_PATH;
        }
  
@@@ -4906,19 -4891,18 +4906,19 @@@ static int create_dev_resources(struct 
        if (ret)
                goto error0;
  
 -      devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, &cq_attr, NULL);
 -      if (IS_ERR(devr->c0)) {
 -              ret = PTR_ERR(devr->c0);
 +      devr->c0 = rdma_zalloc_drv_obj(ibdev, ib_cq);
 +      if (!devr->c0) {
 +              ret = -ENOMEM;
                goto error1;
        }
 -      devr->c0->device        = &dev->ib_dev;
 -      devr->c0->uobject       = NULL;
 -      devr->c0->comp_handler  = NULL;
 -      devr->c0->event_handler = NULL;
 -      devr->c0->cq_context    = NULL;
 +
 +      devr->c0->device = &dev->ib_dev;
        atomic_set(&devr->c0->usecnt, 0);
  
 +      ret = mlx5_ib_create_cq(devr->c0, &cq_attr, NULL);
 +      if (ret)
 +              goto err_create_cq;
 +
        devr->x0 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL);
        if (IS_ERR(devr->x0)) {
                ret = PTR_ERR(devr->x0);
@@@ -5010,8 -4994,6 +5010,8 @@@ error3
        mlx5_ib_dealloc_xrcd(devr->x0, NULL);
  error2:
        mlx5_ib_destroy_cq(devr->c0, NULL);
 +err_create_cq:
 +      kfree(devr->c0);
  error1:
        mlx5_ib_dealloc_pd(devr->p0, NULL);
  error0:
@@@ -5030,7 -5012,6 +5030,7 @@@ static void destroy_dev_resources(struc
        mlx5_ib_dealloc_xrcd(devr->x0, NULL);
        mlx5_ib_dealloc_xrcd(devr->x1, NULL);
        mlx5_ib_destroy_cq(devr->c0, NULL);
 +      kfree(devr->c0);
        mlx5_ib_dealloc_pd(devr->p0, NULL);
        kfree(devr->p0);
  
@@@ -6063,6 -6044,7 +6063,6 @@@ static int mlx5_ib_stage_init_init(stru
        if (mlx5_use_mad_ifc(dev))
                get_ext_port_caps(dev);
  
 -      dev->ib_dev.owner               = THIS_MODULE;
        dev->ib_dev.node_type           = RDMA_NODE_IB_CA;
        dev->ib_dev.local_dma_lkey      = 0 /* not supported for now */;
        dev->ib_dev.phys_port_cnt       = dev->num_ports;
@@@ -6142,13 -6124,8 +6142,13 @@@ static void mlx5_ib_stage_flow_db_clean
  }
  
  static const struct ib_device_ops mlx5_ib_dev_ops = {
 +      .owner = THIS_MODULE,
 +      .driver_id = RDMA_DRIVER_MLX5,
 +      .uverbs_abi_ver = MLX5_IB_UVERBS_ABI_VERSION,
 +
        .add_gid = mlx5_ib_add_gid,
        .alloc_mr = mlx5_ib_alloc_mr,
 +      .alloc_mr_integrity = mlx5_ib_alloc_mr_integrity,
        .alloc_pd = mlx5_ib_alloc_pd,
        .alloc_ucontext = mlx5_ib_alloc_ucontext,
        .attach_mcast = mlx5_ib_mcg_attach,
        .get_dma_mr = mlx5_ib_get_dma_mr,
        .get_link_layer = mlx5_ib_port_link_layer,
        .map_mr_sg = mlx5_ib_map_mr_sg,
 +      .map_mr_sg_pi = mlx5_ib_map_mr_sg_pi,
        .mmap = mlx5_ib_mmap,
        .modify_cq = mlx5_ib_modify_cq,
        .modify_device = mlx5_ib_modify_device,
        .resize_cq = mlx5_ib_resize_cq,
  
        INIT_RDMA_OBJ_SIZE(ib_ah, mlx5_ib_ah, ibah),
 +      INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq),
        INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd),
        INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq),
        INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx5_ib_ucontext, ibucontext),
@@@ -6246,6 -6221,7 +6246,6 @@@ static int mlx5_ib_stage_caps_init(stru
        struct mlx5_core_dev *mdev = dev->mdev;
        int err;
  
 -      dev->ib_dev.uverbs_abi_ver      = MLX5_IB_UVERBS_ABI_VERSION;
        dev->ib_dev.uverbs_cmd_mask     =
                (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
                (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
        if (mlx5_accel_ipsec_device_caps(dev->mdev) &
            MLX5_ACCEL_IPSEC_CAP_DEVICE)
                ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_flow_ipsec_ops);
 -      dev->ib_dev.driver_id = RDMA_DRIVER_MLX5;
        ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_ops);
  
        if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS))
@@@ -1459,8 -1459,6 +1459,6 @@@ static void qib_fill_device_attr(struc
        rdi->dparms.props.max_cq = ib_qib_max_cqs;
        rdi->dparms.props.max_cqe = ib_qib_max_cqes;
        rdi->dparms.props.max_ah = ib_qib_max_ahs;
-       rdi->dparms.props.max_mr = rdi->lkey_table.max;
-       rdi->dparms.props.max_fmr = rdi->lkey_table.max;
        rdi->dparms.props.max_map_per_fmr = 32767;
        rdi->dparms.props.max_qp_rd_atom = QIB_MAX_RDMA_ATOMIC;
        rdi->dparms.props.max_qp_init_rd_atom = 255;
  }
  
  static const struct ib_device_ops qib_dev_ops = {
 +      .owner = THIS_MODULE,
 +      .driver_id = RDMA_DRIVER_QIB,
 +
        .init_port = qib_create_port_files,
        .modify_device = qib_modify_device,
        .process_mad = qib_process_mad,
@@@ -1548,6 -1543,7 +1546,6 @@@ int qib_register_ib_device(struct qib_d
        if (!ib_qib_sys_image_guid)
                ib_qib_sys_image_guid = ppd->guid;
  
 -      ibdev->owner = THIS_MODULE;
        ibdev->node_guid = ppd->guid;
        ibdev->phys_port_cnt = dd->num_pports;
        ibdev->dev.parent = &dd->pcidev->dev;
        rdma_set_device_sysfs_group(&dd->verbs_dev.rdi.ibdev, &qib_attr_group);
  
        ib_set_device_ops(ibdev, &qib_dev_ops);
 -      ret = rvt_register_device(&dd->verbs_dev.rdi, RDMA_DRIVER_QIB);
 +      ret = rvt_register_device(&dd->verbs_dev.rdi);
        if (ret)
                goto err_tx;
  
@@@ -96,6 -96,8 +96,8 @@@ int rvt_driver_mr_init(struct rvt_dev_i
        for (i = 0; i < rdi->lkey_table.max; i++)
                RCU_INIT_POINTER(rdi->lkey_table.table[i], NULL);
  
+       rdi->dparms.props.max_mr = rdi->lkey_table.max;
+       rdi->dparms.props.max_fmr = rdi->lkey_table.max;
        return 0;
  }
  
@@@ -560,7 -562,8 +562,7 @@@ int rvt_dereg_mr(struct ib_mr *ibmr, st
        if (ret)
                goto out;
        rvt_deinit_mregion(&mr->mr);
 -      if (mr->umem)
 -              ib_umem_release(mr->umem);
 +      ib_umem_release(mr->umem);
        kfree(mr);
  out:
        return ret;
@@@ -594,7 -594,8 +594,8 @@@ static int alloc_qpn(struct rvt_dev_inf
                        offset = qpt->incr | ((offset & 1) ^ 1);
                }
                /* there can be no set bits in low-order QoS bits */
-               WARN_ON(offset & (BIT(rdi->dparms.qos_shift) - 1));
+               WARN_ON(rdi->dparms.qos_shift > 1 &&
+                       offset & ((BIT(rdi->dparms.qos_shift - 1) - 1) << 1));
                qpn = mk_qpn(qpt, map, offset);
        }
  
@@@ -988,7 -989,9 +989,7 @@@ struct ib_qp *rvt_create_qp(struct ib_p
        case IB_QPT_UC:
        case IB_QPT_RC:
        case IB_QPT_UD:
 -              sz = sizeof(struct rvt_sge) *
 -                      init_attr->cap.max_send_sge +
 -                      sizeof(struct rvt_swqe);
 +              sz = struct_size(swq, sg_list, init_attr->cap.max_send_sge);
                swq = vzalloc_node(array_size(sz, sqsize), rdi->dparms.node);
                if (!swq)
                        return ERR_PTR(-ENOMEM);
@@@ -1853,9 -1856,10 +1854,9 @@@ static inline int rvt_qp_is_avail
  
        /* see rvt_qp_wqe_unreserve() */
        smp_mb__before_atomic();
 -      reserved_used = atomic_read(&qp->s_reserved_used);
        if (unlikely(reserved_op)) {
                /* see rvt_qp_wqe_unreserve() */
 -              smp_mb__before_atomic();
 +              reserved_used = atomic_read(&qp->s_reserved_used);
                if (reserved_used >= rdi->dparms.reserved_operations)
                        return -ENOMEM;
                return 0;
        /* non-reserved operations */
        if (likely(qp->s_avail))
                return 0;
 -      slast = READ_ONCE(qp->s_last);
 +      /* See rvt_qp_complete_swqe() */
 +      slast = smp_load_acquire(&qp->s_last);
        if (qp->s_head >= slast)
                avail = qp->s_size - (qp->s_head - slast);
        else
                avail = slast - qp->s_head;
  
 -      /* see rvt_qp_wqe_unreserve() */
 -      smp_mb__before_atomic();
        reserved_used = atomic_read(&qp->s_reserved_used);
        avail =  avail - 1 -
                (rdi->dparms.reserved_operations - reserved_used);
@@@ -2662,16 -2667,27 +2663,16 @@@ void rvt_send_complete(struct rvt_qp *q
                       enum ib_wc_status status)
  {
        u32 old_last, last;
 -      struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
 +      struct rvt_dev_info *rdi;
  
        if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_OR_FLUSH_SEND))
                return;
 +      rdi = ib_to_rvt(qp->ibqp.device);
  
 -      last = qp->s_last;
 -      old_last = last;
 -      trace_rvt_qp_send_completion(qp, wqe, last);
 -      if (++last >= qp->s_size)
 -              last = 0;
 -      trace_rvt_qp_send_completion(qp, wqe, last);
 -      qp->s_last = last;
 -      /* See post_send() */
 -      barrier();
 -      rvt_put_qp_swqe(qp, wqe);
 -
 -      rvt_qp_swqe_complete(qp,
 -                           wqe,
 -                           rdi->wc_opcode[wqe->wr.opcode],
 -                           status);
 -
 +      old_last = qp->s_last;
 +      trace_rvt_qp_send_completion(qp, wqe, old_last);
 +      last = rvt_qp_complete_swqe(qp, wqe, rdi->wc_opcode[wqe->wr.opcode],
 +                                  status);
        if (qp->s_acked == old_last)
                qp->s_acked = last;
        if (qp->s_cur == old_last)
@@@ -1,3 -1,4 +1,4 @@@
+ # SPDX-License-Identifier: GPL-2.0-only
  config INFINIBAND_IPOIB
        tristate "IP-over-InfiniBand"
        depends on NETDEVICES && INET && (IPV6 || IPV6=n)
@@@ -6,7 -7,7 +7,7 @@@
          transports IP packets over InfiniBand so you can use your IB
          device as a fancy NIC.
  
 -        See Documentation/infiniband/ipoib.txt for more information
 +        See Documentation/infiniband/ipoib.rst for more information
  
  config INFINIBAND_IPOIB_CM
        bool "IP-over-InfiniBand Connected Mode support"
@@@ -1,3 -1,4 +1,4 @@@
+ // SPDX-License-Identifier: GPL-2.0-or-later
  /*******************************************************************************
   * This file contains iSCSI extentions for RDMA (iSER) Verbs
   *
@@@ -5,15 -6,6 +6,6 @@@
   *
   * Nicholas A. Bellinger <nab@linux-iscsi.org>
   *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
   ****************************************************************************/
  
  #include <linux/string.h>
@@@ -141,7 -133,7 +133,7 @@@ isert_create_qp(struct isert_conn *iser
        attr.sq_sig_type = IB_SIGNAL_REQ_WR;
        attr.qp_type = IB_QPT_RC;
        if (device->pi_capable)
 -              attr.create_flags |= IB_QP_CREATE_SIGNATURE_EN;
 +              attr.create_flags |= IB_QP_CREATE_INTEGRITY_EN;
  
        ret = rdma_create_qp(cma_id, device->pd, &attr);
        if (ret) {
@@@ -317,7 -309,7 +309,7 @@@ isert_create_device_ib_res(struct isert
  
        /* Check signature cap */
        device->pi_capable = ib_dev->attrs.device_cap_flags &
 -                           IB_DEVICE_SIGNATURE_HANDOVER ? true : false;
 +                           IB_DEVICE_INTEGRITY_HANDOVER ? true : false;
  
        return 0;
  
@@@ -1677,7 -1669,7 +1669,7 @@@ isert_rdma_write_done(struct ib_cq *cq
  
        isert_dbg("Cmd %p\n", isert_cmd);
  
 -      ret = isert_check_pi_status(cmd, isert_cmd->rw.sig->sig_mr);
 +      ret = isert_check_pi_status(cmd, isert_cmd->rw.reg->mr);
        isert_rdma_rw_ctx_destroy(isert_cmd, isert_conn);
  
        if (ret) {
@@@ -1723,7 -1715,7 +1715,7 @@@ isert_rdma_read_done(struct ib_cq *cq, 
        iscsit_stop_dataout_timer(cmd);
  
        if (isert_prot_cmd(isert_conn, se_cmd))
 -              ret = isert_check_pi_status(se_cmd, isert_cmd->rw.sig->sig_mr);
 +              ret = isert_check_pi_status(se_cmd, isert_cmd->rw.reg->mr);
        isert_rdma_rw_ctx_destroy(isert_cmd, isert_conn);
        cmd->write_data_done = 0;
  
@@@ -2067,7 -2059,8 +2059,7 @@@ isert_put_text_rsp(struct iscsi_cmd *cm
  }
  
  static inline void
 -isert_set_dif_domain(struct se_cmd *se_cmd, struct ib_sig_attrs *sig_attrs,
 -                   struct ib_sig_domain *domain)
 +isert_set_dif_domain(struct se_cmd *se_cmd, struct ib_sig_domain *domain)
  {
        domain->sig_type = IB_SIG_TYPE_T10_DIF;
        domain->sig.dif.bg_type = IB_T10DIF_CRC;
@@@ -2095,17 -2088,17 +2087,17 @@@ isert_set_sig_attrs(struct se_cmd *se_c
        case TARGET_PROT_DIN_INSERT:
        case TARGET_PROT_DOUT_STRIP:
                sig_attrs->mem.sig_type = IB_SIG_TYPE_NONE;
 -              isert_set_dif_domain(se_cmd, sig_attrs, &sig_attrs->wire);
 +              isert_set_dif_domain(se_cmd, &sig_attrs->wire);
                break;
        case TARGET_PROT_DOUT_INSERT:
        case TARGET_PROT_DIN_STRIP:
                sig_attrs->wire.sig_type = IB_SIG_TYPE_NONE;
 -              isert_set_dif_domain(se_cmd, sig_attrs, &sig_attrs->mem);
 +              isert_set_dif_domain(se_cmd, &sig_attrs->mem);
                break;
        case TARGET_PROT_DIN_PASS:
        case TARGET_PROT_DOUT_PASS:
 -              isert_set_dif_domain(se_cmd, sig_attrs, &sig_attrs->wire);
 -              isert_set_dif_domain(se_cmd, sig_attrs, &sig_attrs->mem);
 +              isert_set_dif_domain(se_cmd, &sig_attrs->wire);
 +              isert_set_dif_domain(se_cmd, &sig_attrs->mem);
                break;
        default:
                isert_err("Unsupported PI operation %d\n", se_cmd->prot_op);
@@@ -148,6 -148,7 +148,7 @@@ MODULE_PARM_DESC(ch_count
  
  static void srp_add_one(struct ib_device *device);
  static void srp_remove_one(struct ib_device *device, void *client_data);
+ static void srp_rename_dev(struct ib_device *device, void *client_data);
  static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc);
  static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
                const char *opname);
@@@ -162,7 -163,8 +163,8 @@@ static struct workqueue_struct *srp_rem
  static struct ib_client srp_client = {
        .name   = "srp",
        .add    = srp_add_one,
-       .remove = srp_remove_one
+       .remove = srp_remove_one,
+       .rename = srp_rename_dev
  };
  
  static struct ib_sa_client srp_sa_client;
@@@ -3481,14 -3483,13 +3483,14 @@@ static const match_table_t srp_opt_toke
   * @net:         [in]  Network namespace.
   * @sa:                  [out] Address family, IP address and port number.
   * @addr_port_str: [in]  IP address and port number.
 + * @has_port:    [out] Whether or not @addr_port_str includes a port number.
   *
   * Parse the following address formats:
   * - IPv4: <ip_address>:<port>, e.g. 1.2.3.4:5.
   * - IPv6: \[<ipv6_address>\]:<port>, e.g. [1::2:3%4]:5.
   */
  static int srp_parse_in(struct net *net, struct sockaddr_storage *sa,
 -                      const char *addr_port_str)
 +                      const char *addr_port_str, bool *has_port)
  {
        char *addr_end, *addr = kstrdup(addr_port_str, GFP_KERNEL);
        char *port_str;
        if (!addr)
                return -ENOMEM;
        port_str = strrchr(addr, ':');
 -      if (!port_str)
 -              return -EINVAL;
 -      *port_str++ = '\0';
 +      if (port_str && strchr(port_str, ']'))
 +              port_str = NULL;
 +      if (port_str)
 +              *port_str++ = '\0';
 +      if (has_port)
 +              *has_port = port_str != NULL;
        ret = inet_pton_with_scope(net, AF_INET, addr, port_str, sa);
        if (ret && addr[0]) {
                addr_end = addr + strlen(addr) - 1;
@@@ -3524,7 -3522,6 +3526,7 @@@ static int srp_parse_options(struct ne
        char *p;
        substring_t args[MAX_OPT_ARGS];
        unsigned long long ull;
 +      bool has_port;
        int opt_mask = 0;
        int token;
        int ret = -EINVAL;
                                ret = -ENOMEM;
                                goto out;
                        }
 -                      ret = srp_parse_in(net, &target->rdma_cm.src.ss, p);
 +                      ret = srp_parse_in(net, &target->rdma_cm.src.ss, p,
 +                                         NULL);
                        if (ret < 0) {
                                pr_warn("bad source parameter '%s'\n", p);
                                kfree(p);
                                ret = -ENOMEM;
                                goto out;
                        }
 -                      ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p);
 +                      ret = srp_parse_in(net, &target->rdma_cm.dst.ss, p,
 +                                         &has_port);
 +                      if (!has_port)
 +                              ret = -EINVAL;
                        if (ret < 0) {
                                pr_warn("bad dest parameter '%s'\n", p);
                                kfree(p);
@@@ -4121,6 -4114,20 +4123,20 @@@ free_host
        return NULL;
  }
  
+ static void srp_rename_dev(struct ib_device *device, void *client_data)
+ {
+       struct srp_device *srp_dev = client_data;
+       struct srp_host *host, *tmp_host;
+       list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
+               char name[IB_DEVICE_NAME_MAX + 8];
+               snprintf(name, sizeof(name), "srp-%s-%d",
+                        dev_name(&device->dev), host->port);
+               device_rename(&host->dev, name);
+       }
+ }
  static void srp_add_one(struct ib_device *device)
  {
        struct srp_device *srp_dev;
@@@ -316,7 -316,7 +316,7 @@@ static int mlx5_internal_err_ret_value(
        case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT:
        case MLX5_CMD_OP_DEALLOC_MEMIC:
        case MLX5_CMD_OP_PAGE_FAULT_RESUME:
 -      case MLX5_CMD_OP_QUERY_HOST_PARAMS:
 +      case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
                return MLX5_CMD_STAT_OK;
  
        case MLX5_CMD_OP_QUERY_HCA_CAP:
        case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
        case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
        case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
+       case MLX5_CMD_OP_CREATE_UCTX:
+       case MLX5_CMD_OP_DESTROY_UCTX:
+       case MLX5_CMD_OP_CREATE_UMEM:
+       case MLX5_CMD_OP_DESTROY_UMEM:
        case MLX5_CMD_OP_ALLOC_MEMIC:
                *status = MLX5_DRIVER_STATUS_ABORTED;
                *synd = MLX5_DRIVER_SYND;
@@@ -628,7 -632,11 +632,11 @@@ const char *mlx5_command_str(int comman
        MLX5_COMMAND_STR_CASE(QUERY_MODIFY_HEADER_CONTEXT);
        MLX5_COMMAND_STR_CASE(ALLOC_MEMIC);
        MLX5_COMMAND_STR_CASE(DEALLOC_MEMIC);
 -      MLX5_COMMAND_STR_CASE(QUERY_HOST_PARAMS);
 +      MLX5_COMMAND_STR_CASE(QUERY_ESW_FUNCTIONS);
+       MLX5_COMMAND_STR_CASE(CREATE_UCTX);
+       MLX5_COMMAND_STR_CASE(DESTROY_UCTX);
+       MLX5_COMMAND_STR_CASE(CREATE_UMEM);
+       MLX5_COMMAND_STR_CASE(DESTROY_UMEM);
        default: return "unknown command opcode";
        }
  }
@@@ -1604,7 -1612,27 +1612,27 @@@ void mlx5_cmd_flush(struct mlx5_core_de
  
  static int status_to_err(u8 status)
  {
-       return status ? -1 : 0; /* TBD more meaningful codes */
+       switch (status) {
+       case MLX5_CMD_DELIVERY_STAT_OK:
+       case MLX5_DRIVER_STATUS_ABORTED:
+               return 0;
+       case MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR:
+       case MLX5_CMD_DELIVERY_STAT_TOK_ERR:
+               return -EBADR;
+       case MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR:
+       case MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR:
+       case MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR:
+               return -EFAULT; /* Bad address */
+       case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR:
+       case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR:
+       case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR:
+       case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR:
+               return -ENOMSG;
+       case MLX5_CMD_DELIVERY_STAT_FW_ERR:
+               return -EIO;
+       default:
+               return -EINVAL;
+       }
  }
  
  static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size,
@@@ -26,7 -26,7 +26,7 @@@ static int mlx5_peer_pf_disable_hca(str
  
        MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA);
        MLX5_SET(disable_hca_in, in, function_id, 0);
-       MLX5_SET(enable_hca_in, in, embedded_cpu_function, 0);
+       MLX5_SET(disable_hca_in, in, embedded_cpu_function, 0);
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  }
  
@@@ -83,3 -83,30 +83,3 @@@ void mlx5_ec_cleanup(struct mlx5_core_d
  
        mlx5_peer_pf_cleanup(dev);
  }
 -
 -static int mlx5_query_host_params_context(struct mlx5_core_dev *dev,
 -                                        u32 *out, int outlen)
 -{
 -      u32 in[MLX5_ST_SZ_DW(query_host_params_in)] = {};
 -
 -      MLX5_SET(query_host_params_in, in, opcode,
 -               MLX5_CMD_OP_QUERY_HOST_PARAMS);
 -
 -      return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
 -}
 -
 -int mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf)
 -{
 -      u32 out[MLX5_ST_SZ_DW(query_host_params_out)] = {};
 -      int err;
 -
 -      err = mlx5_query_host_params_context(dev, out, sizeof(out));
 -      if (err)
 -              return err;
 -
 -      *num_vf = MLX5_GET(query_host_params_out, out,
 -                         host_params_context.host_num_of_vfs);
 -      mlx5_core_dbg(dev, "host_num_of_vfs %d\n", *num_vf);
 -
 -      return 0;
 -}
@@@ -65,9 -65,26 +65,26 @@@ static void mlx5e_rep_indr_unregister_b
  static void mlx5e_rep_get_drvinfo(struct net_device *dev,
                                  struct ethtool_drvinfo *drvinfo)
  {
+       struct mlx5e_priv *priv = netdev_priv(dev);
+       struct mlx5_core_dev *mdev = priv->mdev;
        strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
                sizeof(drvinfo->driver));
        strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
+       snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+                "%d.%d.%04d (%.16s)",
+                fw_rev_maj(mdev), fw_rev_min(mdev),
+                fw_rev_sub(mdev), mdev->board_id);
+ }
+ static void mlx5e_uplink_rep_get_drvinfo(struct net_device *dev,
+                                        struct ethtool_drvinfo *drvinfo)
+ {
+       struct mlx5e_priv *priv = netdev_priv(dev);
+       mlx5e_rep_get_drvinfo(dev, drvinfo);
+       strlcpy(drvinfo->bus_info, pci_name(priv->mdev->pdev),
+               sizeof(drvinfo->bus_info));
  }
  
  static const struct counter_desc sw_rep_stats_desc[] = {
@@@ -363,7 -380,7 +380,7 @@@ static const struct ethtool_ops mlx5e_v
  };
  
  static const struct ethtool_ops mlx5e_uplink_rep_ethtool_ops = {
-       .get_drvinfo       = mlx5e_rep_get_drvinfo,
+       .get_drvinfo       = mlx5e_uplink_rep_get_drvinfo,
        .get_link          = ethtool_op_get_link,
        .get_strings       = mlx5e_rep_get_strings,
        .get_sset_count    = mlx5e_rep_get_sset_count,
@@@ -796,7 -813,7 +813,7 @@@ static int mlx5e_nic_rep_netdevice_even
        struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
  
        if (!mlx5e_tc_tun_device_to_offload(priv, netdev) &&
-           !is_vlan_dev(netdev))
+           !(is_vlan_dev(netdev) && vlan_dev_real_dev(netdev) == rpriv->netdev))
                return NOTIFY_OK;
  
        switch (event) {
@@@ -1334,6 -1351,7 +1351,7 @@@ static const struct net_device_ops mlx5
        .ndo_get_vf_stats        = mlx5e_get_vf_stats,
        .ndo_set_vf_vlan         = mlx5e_uplink_rep_set_vf_vlan,
        .ndo_get_port_parent_id  = mlx5e_rep_get_port_parent_id,
+       .ndo_set_features        = mlx5e_set_features,
  };
  
  bool mlx5e_eswitch_rep(struct net_device *netdev)
@@@ -1408,10 -1426,9 +1426,9 @@@ static void mlx5e_build_rep_netdev(stru
  
        netdev->watchdog_timeo    = 15 * HZ;
  
+       netdev->features       |= NETIF_F_NETNS_LOCAL;
  
-       netdev->features         |= NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
-       netdev->hw_features      |= NETIF_F_HW_TC;
+       netdev->hw_features    |= NETIF_F_HW_TC;
        netdev->hw_features    |= NETIF_F_SG;
        netdev->hw_features    |= NETIF_F_IP_CSUM;
        netdev->hw_features    |= NETIF_F_IPV6_CSUM;
        netdev->hw_features    |= NETIF_F_TSO6;
        netdev->hw_features    |= NETIF_F_RXCSUM;
  
-       if (rep->vport != MLX5_VPORT_UPLINK)
+       if (rep->vport == MLX5_VPORT_UPLINK)
+               netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+       else
                netdev->features |= NETIF_F_VLAN_CHALLENGED;
  
        netdev->features |= netdev->hw_features;
@@@ -1752,7 -1771,7 +1771,7 @@@ mlx5e_vport_rep_load(struct mlx5_core_d
        }
  
        rpriv->netdev = netdev;
 -      rep->rep_if[REP_ETH].priv = rpriv;
 +      rep->rep_data[REP_ETH].priv = rpriv;
        INIT_LIST_HEAD(&rpriv->vport_sqs_list);
  
        if (rep->vport == MLX5_VPORT_UPLINK) {
@@@ -1826,17 -1845,16 +1845,17 @@@ static void *mlx5e_vport_rep_get_proto_
        return rpriv->netdev;
  }
  
 +static const struct mlx5_eswitch_rep_ops rep_ops = {
 +      .load = mlx5e_vport_rep_load,
 +      .unload = mlx5e_vport_rep_unload,
 +      .get_proto_dev = mlx5e_vport_rep_get_proto_dev
 +};
 +
  void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev)
  {
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
 -      struct mlx5_eswitch_rep_if rep_if = {};
 -
 -      rep_if.load = mlx5e_vport_rep_load;
 -      rep_if.unload = mlx5e_vport_rep_unload;
 -      rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
  
 -      mlx5_eswitch_register_vport_reps(esw, &rep_if, REP_ETH);
 +      mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_ETH);
  }
  
  void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev)
@@@ -1526,7 -1526,7 +1526,7 @@@ static void node_guid_gen_from_mac(u64 
  static void esw_apply_vport_conf(struct mlx5_eswitch *esw,
                                 struct mlx5_vport *vport)
  {
-       int vport_num = vport->vport;
+       u16 vport_num = vport->vport;
  
        if (esw->manager_vport == vport_num)
                return;
@@@ -1686,23 -1686,13 +1686,23 @@@ static int eswitch_vport_event(struct n
        return NOTIFY_OK;
  }
  
 +int mlx5_esw_query_functions(struct mlx5_core_dev *dev, u32 *out, int outlen)
 +{
 +      u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
 +
 +      MLX5_SET(query_esw_functions_in, in, opcode,
 +               MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
 +
 +      return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
 +}
 +
  /* Public E-Switch API */
  #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
  
  int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
  {
 -      int vf_nvports = 0, total_nvports = 0;
        struct mlx5_vport *vport;
 +      int total_nvports = 0;
        int err;
        int i, enabled_events;
  
        esw_info(esw->dev, "E-Switch enable SRIOV: nvfs(%d) mode (%d)\n", nvfs, mode);
  
        if (mode == SRIOV_OFFLOADS) {
 -              if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
 -                      err = mlx5_query_host_params_num_vfs(esw->dev, &vf_nvports);
 -                      if (err)
 -                              return err;
 +              if (mlx5_core_is_ecpf_esw_manager(esw->dev))
                        total_nvports = esw->total_vports;
 -              } else {
 -                      vf_nvports = nvfs;
 +              else
                        total_nvports = nvfs + MLX5_SPECIAL_VPORTS(esw->dev);
 -              }
        }
  
        esw->mode = mode;
        } else {
                mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
                mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
 -              err = esw_offloads_init(esw, vf_nvports, total_nvports);
 +              err = esw_offloads_init(esw, nvfs, total_nvports);
        }
  
        if (err)
@@@ -1920,7 -1915,7 +1920,7 @@@ void mlx5_eswitch_cleanup(struct mlx5_e
  
  /* Vport Administration */
  int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
-                              int vport, u8 mac[ETH_ALEN])
+                              u16 vport, u8 mac[ETH_ALEN])
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        u64 node_guid;
@@@ -1964,7 -1959,7 +1964,7 @@@ unlock
  }
  
  int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
-                                int vport, int link_state)
+                                u16 vport, int link_state)
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        int err = 0;
@@@ -1994,7 -1989,7 +1994,7 @@@ unlock
  }
  
  int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
-                                 int vport, struct ifla_vf_info *ivi)
+                                 u16 vport, struct ifla_vf_info *ivi)
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
  
  }
  
  int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
-                                 int vport, u16 vlan, u8 qos, u8 set_flags)
+                                 u16 vport, u16 vlan, u8 qos, u8 set_flags)
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        int err = 0;
@@@ -2052,7 -2047,7 +2052,7 @@@ unlock
  }
  
  int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
-                               int vport, u16 vlan, u8 qos)
+                               u16 vport, u16 vlan, u8 qos)
  {
        u8 set_flags = 0;
  
  }
  
  int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
-                                   int vport, bool spoofchk)
+                                   u16 vport, bool spoofchk)
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        bool pschk;
@@@ -2213,7 -2208,7 +2213,7 @@@ out
  }
  
  int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
-                                int vport, bool setting)
+                                u16 vport, bool setting)
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
  
@@@ -2283,7 -2278,7 +2283,7 @@@ static int normalize_vports_min_rate(st
        return 0;
  }
  
- int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
+ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
                                u32 max_rate, u32 min_rate)
  {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
@@@ -2373,7 -2368,7 +2373,7 @@@ static int mlx5_eswitch_query_vport_dro
  }
  
  int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
-                                int vport_num,
+                                u16 vport_num,
                                 struct ifla_vf_stats *vf_stats)
  {
        struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
@@@ -2457,17 -2452,6 +2457,17 @@@ u8 mlx5_eswitch_mode(struct mlx5_eswitc
  }
  EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
  
 +enum devlink_eswitch_encap_mode
 +mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
 +{
 +      struct mlx5_eswitch *esw;
 +
 +      esw = dev->priv.eswitch;
 +      return ESW_ALLOWED(esw) ? esw->offloads.encap :
 +              DEVLINK_ESWITCH_ENCAP_MODE_NONE;
 +}
 +EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
 +
  bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
  {
        if ((dev0->priv.eswitch->mode == SRIOV_NONE &&
@@@ -173,10 -173,9 +173,10 @@@ struct mlx5_esw_offload 
        struct mutex peer_mutex;
        DECLARE_HASHTABLE(encap_tbl, 8);
        DECLARE_HASHTABLE(mod_hdr_tbl, 8);
 +      const struct mlx5_eswitch_rep_ops *rep_ops[NUM_REP_TYPES];
        u8 inline_mode;
        u64 num_flows;
 -      u8 encap;
 +      enum devlink_eswitch_encap_mode encap;
  };
  
  /* E-Switch MC FDB table hash node */
@@@ -191,7 -190,7 +191,7 @@@ struct mlx5_host_work 
        struct mlx5_eswitch     *esw;
  };
  
 -struct mlx5_host_info {
 +struct mlx5_esw_functions {
        struct mlx5_nb          nb;
        u16                     num_vfs;
  };
@@@ -220,7 -219,7 +220,7 @@@ struct mlx5_eswitch 
        int                     mode;
        int                     nvports;
        u16                     manager_vport;
 -      struct mlx5_host_info   host_info;
 +      struct mlx5_esw_functions esw_funcs;
  };
  
  void esw_offloads_cleanup(struct mlx5_eswitch *esw);
@@@ -247,23 -246,23 +247,23 @@@ void mlx5_eswitch_cleanup(struct mlx5_e
  int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode);
  void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw);
  int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
-                              int vport, u8 mac[ETH_ALEN]);
+                              u16 vport, u8 mac[ETH_ALEN]);
  int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
-                                int vport, int link_state);
+                                u16 vport, int link_state);
  int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
-                               int vport, u16 vlan, u8 qos);
+                               u16 vport, u16 vlan, u8 qos);
  int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
-                                   int vport, bool spoofchk);
+                                   u16 vport, bool spoofchk);
  int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
-                                int vport_num, bool setting);
- int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
+                                u16 vport_num, bool setting);
+ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
                                u32 max_rate, u32 min_rate);
  int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting);
  int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting);
  int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
-                                 int vport, struct ifla_vf_info *ivi);
+                                 u16 vport, struct ifla_vf_info *ivi);
  int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
-                                int vport,
+                                u16 vport,
                                 struct ifla_vf_stats *vf_stats);
  void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule);
  
@@@ -297,7 -296,7 +297,7 @@@ u3
  mlx5_eswitch_get_chain_range(struct mlx5_eswitch *esw);
  
  struct mlx5_flow_handle *
- mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport,
+ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
                                  struct mlx5_flow_destination *dest);
  
  enum {
@@@ -357,11 -356,9 +357,11 @@@ int mlx5_devlink_eswitch_inline_mode_se
                                         struct netlink_ext_ack *extack);
  int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode);
  int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode);
 -int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap,
 +int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
 +                                      enum devlink_eswitch_encap_mode encap,
                                        struct netlink_ext_ack *extack);
 -int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap);
 +int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
 +                                      enum devlink_eswitch_encap_mode *encap);
  void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type);
  
  int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
  int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
                                 struct mlx5_esw_flow_attr *attr);
  int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
-                                 int vport, u16 vlan, u8 qos, u8 set_flags);
+                                 u16 vport, u16 vlan, u8 qos, u8 set_flags);
  
  static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev,
                                                       u8 vlan_depth)
@@@ -389,8 -386,6 +389,8 @@@ bool mlx5_esw_lag_prereq(struct mlx5_co
  bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
                               struct mlx5_core_dev *dev1);
  
 +int mlx5_esw_query_functions(struct mlx5_core_dev *dev, u32 *out, int outlen);
 +
  #define MLX5_DEBUG_ESWITCH_MASK BIT(3)
  
  #define esw_info(__dev, format, ...)                  \
@@@ -409,18 -404,6 +409,18 @@@ static inline u16 mlx5_eswitch_manager_
                MLX5_VPORT_ECPF : MLX5_VPORT_PF;
  }
  
 +static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev)
 +{
 +      /* Ideally device should have the functions changed supported
 +       * capability regardless of it being ECPF or PF wherever such
 +       * event should be processed such as on eswitch manager device.
 +       * However, some ECPF based device might not have this capability
 +       * set. Hence OR for ECPF check to cover such device.
 +       */
 +      return MLX5_CAP_ESW(dev, esw_functions_changed) ||
 +             mlx5_core_is_ecpf_esw_manager(dev);
 +}
 +
  static inline int mlx5_eswitch_uplink_idx(struct mlx5_eswitch *esw)
  {
        /* Uplink always locate at the last element of the array.*/
@@@ -447,7 -430,7 +447,7 @@@ static inline int mlx5_eswitch_vport_nu
        return vport_num;
  }
  
- static inline int mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw,
+ static inline u16 mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw,
                                                  int index)
  {
        if (index == mlx5_eswitch_ecpf_idx(esw) &&
@@@ -515,12 -498,6 +515,12 @@@ static inline void mlx5_eswitch_cleanup
  static inline int  mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { return 0; }
  static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) {}
  static inline bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1) { return true; }
 +static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
 +static inline int
 +mlx5_esw_query_functions(struct mlx5_core_dev *dev, u32 *out, int outlen)
 +{
 +      return -EOPNOTSUPP;
 +}
  
  #define FDB_MAX_CHAIN 1
  #define FDB_SLOW_PATH_CHAIN (FDB_MAX_CHAIN + 1)
@@@ -41,6 -41,7 +41,6 @@@
  #include "en.h"
  #include "fs_core.h"
  #include "lib/devcom.h"
 -#include "ecpf.h"
  #include "lib/eq.h"
  
  /* There are two match-all miss flows, one for unicast dst mac and
@@@ -56,7 -57,7 +56,7 @@@
  static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw,
                                                     u16 vport_num)
  {
-       u16 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
+       int idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
  
        WARN_ON(idx > esw->total_vports - 1);
        return &esw->offloads.vport_reps[idx];
@@@ -332,7 -333,7 +332,7 @@@ static int esw_set_global_vlan_pop(stru
        esw_debug(esw->dev, "%s applying global %s policy\n", __func__, val ? "pop" : "none");
        for (vf_vport = 1; vf_vport < esw->enabled_vports; vf_vport++) {
                rep = &esw->offloads.vport_reps[vf_vport];
 -              if (atomic_read(&rep->rep_if[REP_ETH].state) != REP_LOADED)
 +              if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
                        continue;
  
                err = __mlx5_eswitch_set_vport_vlan(esw, rep->vport, 0, 0, val);
@@@ -514,7 -515,8 +514,8 @@@ out
  }
  
  struct mlx5_flow_handle *
- mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn)
+ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, u16 vport,
+                                   u32 sqn)
  {
        struct mlx5_flow_act flow_act = {0};
        struct mlx5_flow_destination dest = {};
@@@ -1180,7 -1182,7 +1181,7 @@@ static void esw_destroy_vport_rx_group(
  }
  
  struct mlx5_flow_handle *
- mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport,
+ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
                                  struct mlx5_flow_destination *dest)
  {
        struct mlx5_flow_act flow_act = {0};
@@@ -1276,7 -1278,7 +1277,7 @@@ int esw_offloads_init_reps(struct mlx5_
                ether_addr_copy(rep->hw_id, hw_id);
  
                for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
 -                      atomic_set(&rep->rep_if[rep_type].state,
 +                      atomic_set(&rep->rep_data[rep_type].state,
                                   REP_UNREGISTERED);
        }
  
  static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
                                      struct mlx5_eswitch_rep *rep, u8 rep_type)
  {
 -      if (atomic_cmpxchg(&rep->rep_if[rep_type].state,
 +      if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
                           REP_LOADED, REP_REGISTERED) == REP_LOADED)
 -              rep->rep_if[rep_type].unload(rep);
 +              esw->offloads.rep_ops[rep_type]->unload(rep);
  }
  
  static void __unload_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
@@@ -1349,11 -1351,11 +1350,11 @@@ static int __esw_offloads_load_rep(stru
  {
        int err = 0;
  
 -      if (atomic_cmpxchg(&rep->rep_if[rep_type].state,
 +      if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
                           REP_REGISTERED, REP_LOADED) == REP_REGISTERED) {
 -              err = rep->rep_if[rep_type].load(esw->dev, rep);
 +              err = esw->offloads.rep_ops[rep_type]->load(esw->dev, rep);
                if (err)
 -                      atomic_set(&rep->rep_if[rep_type].state,
 +                      atomic_set(&rep->rep_data[rep_type].state,
                                   REP_REGISTERED);
        }
  
@@@ -1436,13 -1438,34 +1437,13 @@@ err_reps
        return err;
  }
  
 -static int __load_reps_all_vport(struct mlx5_eswitch *esw, int nvports,
 -                               u8 rep_type)
 -{
 -      int err;
 -
 -      /* Special vports must be loaded first. */
 -      err = __load_reps_special_vport(esw, rep_type);
 -      if (err)
 -              return err;
 -
 -      err = __load_reps_vf_vport(esw, nvports, rep_type);
 -      if (err)
 -              goto err_vfs;
 -
 -      return 0;
 -
 -err_vfs:
 -      __unload_reps_special_vport(esw, rep_type);
 -      return err;
 -}
 -
 -static int esw_offloads_load_all_reps(struct mlx5_eswitch *esw, int nvports)
 +static int esw_offloads_load_special_vport(struct mlx5_eswitch *esw)
  {
        u8 rep_type = 0;
        int err;
  
        for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
 -              err = __load_reps_all_vport(esw, nvports, rep_type);
 +              err = __load_reps_special_vport(esw, rep_type);
                if (err)
                        goto err_reps;
        }
  
  err_reps:
        while (rep_type-- > 0)
 -              __unload_reps_all_vport(esw, nvports, rep_type);
 +              __unload_reps_special_vport(esw, rep_type);
        return err;
  }
  
@@@ -1709,13 -1732,14 +1710,14 @@@ static void esw_prio_tag_acls_cleanup(s
        struct mlx5_vport *vport;
        int i;
  
-       mlx5_esw_for_each_vf_vport(esw, i, vport, esw->nvports) {
+       mlx5_esw_for_each_vf_vport(esw, i, vport, esw->dev->priv.sriov.num_vfs) {
                esw_vport_disable_egress_acl(esw, vport);
                esw_vport_disable_ingress_acl(esw, vport);
        }
  }
  
- static int esw_offloads_steering_init(struct mlx5_eswitch *esw, int nvports)
+ static int esw_offloads_steering_init(struct mlx5_eswitch *esw, int vf_nvports,
+                                     int nvports)
  {
        int err;
  
        mutex_init(&esw->fdb_table.offloads.fdb_prio_lock);
  
        if (MLX5_CAP_GEN(esw->dev, prio_tag_required)) {
-               err = esw_prio_tag_acls_config(esw, nvports);
+               err = esw_prio_tag_acls_config(esw, vf_nvports);
                if (err)
                        return err;
        }
@@@ -1760,135 -1784,81 +1762,135 @@@ static void esw_offloads_steering_clean
                esw_prio_tag_acls_cleanup(esw);
  }
  
 -static void esw_host_params_event_handler(struct work_struct *work)
 +static void esw_functions_changed_event_handler(struct work_struct *work)
  {
 +      u32 out[MLX5_ST_SZ_DW(query_esw_functions_out)] = {};
        struct mlx5_host_work *host_work;
        struct mlx5_eswitch *esw;
 -      int err, num_vf = 0;
 +      u16 num_vfs = 0;
 +      int err;
  
        host_work = container_of(work, struct mlx5_host_work, work);
        esw = host_work->esw;
  
 -      err = mlx5_query_host_params_num_vfs(esw->dev, &num_vf);
 -      if (err || num_vf == esw->host_info.num_vfs)
 +      err = mlx5_esw_query_functions(esw->dev, out, sizeof(out));
 +      num_vfs = MLX5_GET(query_esw_functions_out, out,
 +                         host_params_context.host_num_of_vfs);
 +      if (err || num_vfs == esw->esw_funcs.num_vfs)
                goto out;
  
        /* Number of VFs can only change from "0 to x" or "x to 0". */
 -      if (esw->host_info.num_vfs > 0) {
 -              esw_offloads_unload_vf_reps(esw, esw->host_info.num_vfs);
 +      if (esw->esw_funcs.num_vfs > 0) {
 +              esw_offloads_unload_vf_reps(esw, esw->esw_funcs.num_vfs);
        } else {
 -              err = esw_offloads_load_vf_reps(esw, num_vf);
 +              err = esw_offloads_load_vf_reps(esw, num_vfs);
  
                if (err)
                        goto out;
        }
  
 -      esw->host_info.num_vfs = num_vf;
 +      esw->esw_funcs.num_vfs = num_vfs;
  
  out:
        kfree(host_work);
  }
  
 -static int esw_host_params_event(struct notifier_block *nb,
 -                               unsigned long type, void *data)
 +static void esw_emulate_event_handler(struct work_struct *work)
  {
 +      struct mlx5_host_work *host_work =
 +              container_of(work, struct mlx5_host_work, work);
 +      struct mlx5_eswitch *esw = host_work->esw;
 +      int err;
 +
 +      if (esw->esw_funcs.num_vfs) {
 +              err = esw_offloads_load_vf_reps(esw, esw->esw_funcs.num_vfs);
 +              if (err)
 +                      esw_warn(esw->dev, "Load vf reps err=%d\n", err);
 +      }
 +      kfree(host_work);
 +}
 +
 +static int esw_functions_changed_event(struct notifier_block *nb,
 +                                     unsigned long type, void *data)
 +{
 +      struct mlx5_esw_functions *esw_funcs;
        struct mlx5_host_work *host_work;
 -      struct mlx5_host_info *host_info;
        struct mlx5_eswitch *esw;
  
        host_work = kzalloc(sizeof(*host_work), GFP_ATOMIC);
        if (!host_work)
                return NOTIFY_DONE;
  
 -      host_info = mlx5_nb_cof(nb, struct mlx5_host_info, nb);
 -      esw = container_of(host_info, struct mlx5_eswitch, host_info);
 +      esw_funcs = mlx5_nb_cof(nb, struct mlx5_esw_functions, nb);
 +      esw = container_of(esw_funcs, struct mlx5_eswitch, esw_funcs);
  
        host_work->esw = esw;
  
 -      INIT_WORK(&host_work->work, esw_host_params_event_handler);
 +      if (mlx5_eswitch_is_funcs_handler(esw->dev))
 +              INIT_WORK(&host_work->work,
 +                        esw_functions_changed_event_handler);
 +      else
 +              INIT_WORK(&host_work->work, esw_emulate_event_handler);
        queue_work(esw->work_queue, &host_work->work);
  
        return NOTIFY_OK;
  }
  
 +static void esw_functions_changed_event_init(struct mlx5_eswitch *esw,
 +                                           u16 vf_nvports)
 +{
 +      if (mlx5_eswitch_is_funcs_handler(esw->dev)) {
 +              esw->esw_funcs.num_vfs = 0;
 +              MLX5_NB_INIT(&esw->esw_funcs.nb, esw_functions_changed_event,
 +                           ESW_FUNCTIONS_CHANGED);
 +              mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
 +      } else {
 +              esw->esw_funcs.num_vfs = vf_nvports;
 +      }
 +}
 +
 +static void esw_functions_changed_event_cleanup(struct mlx5_eswitch *esw)
 +{
 +      if (!mlx5_eswitch_is_funcs_handler(esw->dev))
 +              return;
 +
 +      mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
 +      flush_workqueue(esw->work_queue);
 +}
 +
  int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports,
                      int total_nvports)
  {
        int err;
  
-       err = esw_offloads_steering_init(esw, total_nvports);
+       err = esw_offloads_steering_init(esw, vf_nvports, total_nvports);
        if (err)
                return err;
  
 -      err = esw_offloads_load_all_reps(esw, vf_nvports);
 +      /* Only load special vports reps. VF reps will be loaded in
 +       * context of functions_changed event handler through real
 +       * or emulated event.
 +       */
 +      err = esw_offloads_load_special_vport(esw);
        if (err)
                goto err_reps;
  
        esw_offloads_devcom_init(esw);
  
 -      if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
 -              MLX5_NB_INIT(&esw->host_info.nb, esw_host_params_event,
 -                           HOST_PARAMS_CHANGE);
 -              mlx5_eq_notifier_register(esw->dev, &esw->host_info.nb);
 -              esw->host_info.num_vfs = vf_nvports;
 -      }
 +      esw_functions_changed_event_init(esw, vf_nvports);
  
        mlx5_rdma_enable_roce(esw->dev);
  
 +      /* Call esw_functions_changed event to load VF reps:
 +       * 1. HW does not support the event then emulate it
 +       * Or
 +       * 2. The event was already notified when num_vfs changed
 +       * and eswitch was in legacy mode
 +       */
 +      esw_functions_changed_event(&esw->esw_funcs.nb.nb,
 +                                  MLX5_EVENT_TYPE_ESW_FUNCTIONS_CHANGED,
 +                                  NULL);
 +
        return 0;
  
  err_reps:
@@@ -1917,10 -1887,19 +1919,10 @@@ static int esw_offloads_stop(struct mlx
  
  void esw_offloads_cleanup(struct mlx5_eswitch *esw)
  {
 -      u16 num_vfs;
 -
 -      if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
 -              mlx5_eq_notifier_unregister(esw->dev, &esw->host_info.nb);
 -              flush_workqueue(esw->work_queue);
 -              num_vfs = esw->host_info.num_vfs;
 -      } else {
 -              num_vfs = esw->dev->priv.sriov.num_vfs;
 -      }
 -
 +      esw_functions_changed_event_cleanup(esw);
        mlx5_rdma_disable_roce(esw->dev);
        esw_offloads_devcom_cleanup(esw);
 -      esw_offloads_unload_all_reps(esw, num_vfs);
 +      esw_offloads_unload_all_reps(esw, esw->esw_funcs.num_vfs);
        esw_offloads_steering_cleanup(esw);
  }
  
@@@ -2160,8 -2139,7 +2162,8 @@@ out
        return 0;
  }
  
 -int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap,
 +int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
 +                                      enum devlink_eswitch_encap_mode encap,
                                        struct netlink_ext_ack *extack)
  {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
        return err;
  }
  
 -int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap)
 +int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
 +                                      enum devlink_eswitch_encap_mode *encap)
  {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
        struct mlx5_eswitch *esw = dev->priv.eswitch;
  }
  
  void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,
 -                                    struct mlx5_eswitch_rep_if *__rep_if,
 +                                    const struct mlx5_eswitch_rep_ops *ops,
                                      u8 rep_type)
  {
 -      struct mlx5_eswitch_rep_if *rep_if;
 +      struct mlx5_eswitch_rep_data *rep_data;
        struct mlx5_eswitch_rep *rep;
        int i;
  
 +      esw->offloads.rep_ops[rep_type] = ops;
        mlx5_esw_for_all_reps(esw, i, rep) {
 -              rep_if = &rep->rep_if[rep_type];
 -              rep_if->load   = __rep_if->load;
 -              rep_if->unload = __rep_if->unload;
 -              rep_if->get_proto_dev = __rep_if->get_proto_dev;
 -              rep_if->priv = __rep_if->priv;
 -
 -              atomic_set(&rep_if->state, REP_REGISTERED);
 +              rep_data = &rep->rep_data[rep_type];
 +              atomic_set(&rep_data->state, REP_REGISTERED);
        }
  }
  EXPORT_SYMBOL(mlx5_eswitch_register_vport_reps);
@@@ -2251,7 -2232,7 +2253,7 @@@ void mlx5_eswitch_unregister_vport_reps
                __unload_reps_all_vport(esw, max_vf, rep_type);
  
        mlx5_esw_for_all_reps(esw, i, rep)
 -              atomic_set(&rep->rep_if[rep_type].state, REP_UNREGISTERED);
 +              atomic_set(&rep->rep_data[rep_type].state, REP_UNREGISTERED);
  }
  EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_reps);
  
@@@ -2260,20 -2241,20 +2262,20 @@@ void *mlx5_eswitch_get_uplink_priv(stru
        struct mlx5_eswitch_rep *rep;
  
        rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
 -      return rep->rep_if[rep_type].priv;
 +      return rep->rep_data[rep_type].priv;
  }
  
  void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw,
-                                int vport,
+                                u16 vport,
                                 u8 rep_type)
  {
        struct mlx5_eswitch_rep *rep;
  
        rep = mlx5_eswitch_get_rep(esw, vport);
  
 -      if (atomic_read(&rep->rep_if[rep_type].state) == REP_LOADED &&
 -          rep->rep_if[rep_type].get_proto_dev)
 -              return rep->rep_if[rep_type].get_proto_dev(rep);
 +      if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
 +          esw->offloads.rep_ops[rep_type]->get_proto_dev)
 +              return esw->offloads.rep_ops[rep_type]->get_proto_dev(rep);
        return NULL;
  }
  EXPORT_SYMBOL(mlx5_eswitch_get_proto_dev);
@@@ -2285,7 -2266,7 +2287,7 @@@ void *mlx5_eswitch_uplink_get_proto_dev
  EXPORT_SYMBOL(mlx5_eswitch_uplink_get_proto_dev);
  
  struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw,
-                                               int vport)
+                                               u16 vport)
  {
        return mlx5_eswitch_get_rep(esw, vport);
  }
@@@ -169,28 -169,18 +169,28 @@@ static struct mlx5_profile profile[] = 
  
  #define FW_INIT_TIMEOUT_MILI          2000
  #define FW_INIT_WAIT_MS                       2
 -#define FW_PRE_INIT_TIMEOUT_MILI      10000
 +#define FW_PRE_INIT_TIMEOUT_MILI      120000
 +#define FW_INIT_WARN_MESSAGE_INTERVAL 20000
  
 -static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
 +static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili,
 +                      u32 warn_time_mili)
  {
 +      unsigned long warn = jiffies + msecs_to_jiffies(warn_time_mili);
        unsigned long end = jiffies + msecs_to_jiffies(max_wait_mili);
        int err = 0;
  
 +      BUILD_BUG_ON(FW_PRE_INIT_TIMEOUT_MILI < FW_INIT_WARN_MESSAGE_INTERVAL);
 +
        while (fw_initializing(dev)) {
                if (time_after(jiffies, end)) {
                        err = -EBUSY;
                        break;
                }
 +              if (warn_time_mili && time_after(jiffies, warn)) {
 +                      mlx5_core_warn(dev, "Waiting for FW initialization, timeout abort in %ds\n",
 +                                     jiffies_to_msecs(end - warn) / 1000);
 +                      warn = jiffies + msecs_to_jiffies(warn_time_mili);
 +              }
                msleep(FW_INIT_WAIT_MS);
        }
  
@@@ -804,16 -794,10 +804,16 @@@ static int mlx5_init_once(struct mlx5_c
                goto err_devcom;
        }
  
 +      err = mlx5_irq_table_init(dev);
 +      if (err) {
 +              mlx5_core_err(dev, "failed to initialize irq table\n");
 +              goto err_devcom;
 +      }
 +
        err = mlx5_eq_table_init(dev);
        if (err) {
                mlx5_core_err(dev, "failed to initialize eq\n");
 -              goto err_devcom;
 +              goto err_irq_cleanup;
        }
  
        err = mlx5_events_init(dev);
                goto err_rl_cleanup;
        }
  
 -      err = mlx5_eswitch_init(dev);
 +      err = mlx5_sriov_init(dev);
        if (err) {
 -              mlx5_core_err(dev, "Failed to init eswitch %d\n", err);
 +              mlx5_core_err(dev, "Failed to init sriov %d\n", err);
                goto err_mpfs_cleanup;
        }
  
 -      err = mlx5_sriov_init(dev);
 +      err = mlx5_eswitch_init(dev);
        if (err) {
 -              mlx5_core_err(dev, "Failed to init sriov %d\n", err);
 -              goto err_eswitch_cleanup;
 +              mlx5_core_err(dev, "Failed to init eswitch %d\n", err);
 +              goto err_sriov_cleanup;
        }
  
        err = mlx5_fpga_init(dev);
        if (err) {
                mlx5_core_err(dev, "Failed to init fpga device %d\n", err);
 -              goto err_sriov_cleanup;
 +              goto err_eswitch_cleanup;
        }
  
        dev->tracer = mlx5_fw_tracer_create(dev);
  
        return 0;
  
 -err_sriov_cleanup:
 -      mlx5_sriov_cleanup(dev);
  err_eswitch_cleanup:
        mlx5_eswitch_cleanup(dev->priv.eswitch);
 +err_sriov_cleanup:
 +      mlx5_sriov_cleanup(dev);
  err_mpfs_cleanup:
        mlx5_mpfs_cleanup(dev);
  err_rl_cleanup:
@@@ -889,8 -873,6 +889,8 @@@ err_events_cleanup
        mlx5_events_cleanup(dev);
  err_eq_cleanup:
        mlx5_eq_table_cleanup(dev);
 +err_irq_cleanup:
 +      mlx5_irq_table_cleanup(dev);
  err_devcom:
        mlx5_devcom_unregister_device(dev->priv.devcom);
  
@@@ -901,8 -883,8 +901,8 @@@ static void mlx5_cleanup_once(struct ml
  {
        mlx5_fw_tracer_destroy(dev->tracer);
        mlx5_fpga_cleanup(dev);
 -      mlx5_sriov_cleanup(dev);
        mlx5_eswitch_cleanup(dev->priv.eswitch);
 +      mlx5_sriov_cleanup(dev);
        mlx5_mpfs_cleanup(dev);
        mlx5_cleanup_rl_table(dev);
        mlx5_vxlan_destroy(dev->vxlan);
        mlx5_cq_debugfs_cleanup(dev);
        mlx5_events_cleanup(dev);
        mlx5_eq_table_cleanup(dev);
 +      mlx5_irq_table_cleanup(dev);
        mlx5_devcom_unregister_device(dev->priv.devcom);
  }
  
@@@ -930,7 -911,7 +930,7 @@@ static int mlx5_function_setup(struct m
  
        /* wait for firmware to accept initialization segments configurations
         */
 -      err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
 +      err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI, FW_INIT_WARN_MESSAGE_INTERVAL);
        if (err) {
                mlx5_core_err(dev, "Firmware over %d MS in pre-initializing state, aborting\n",
                              FW_PRE_INIT_TIMEOUT_MILI);
                return err;
        }
  
 -      err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI);
 +      err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI, 0);
        if (err) {
                mlx5_core_err(dev, "Firmware over %d MS in initializing state, aborting\n",
                              FW_INIT_TIMEOUT_MILI);
@@@ -1047,12 -1028,6 +1047,12 @@@ static int mlx5_load(struct mlx5_core_d
        mlx5_events_start(dev);
        mlx5_pagealloc_start(dev);
  
 +      err = mlx5_irq_table_create(dev);
 +      if (err) {
 +              mlx5_core_err(dev, "Failed to alloc IRQs\n");
 +              goto err_irq_table;
 +      }
 +
        err = mlx5_eq_table_create(dev);
        if (err) {
                mlx5_core_err(dev, "Failed to create EQs\n");
        err = mlx5_core_set_hca_defaults(dev);
        if (err) {
                mlx5_core_err(dev, "Failed to set hca defaults\n");
-               goto err_fs;
+               goto err_sriov;
        }
  
        err = mlx5_sriov_attach(dev);
@@@ -1124,8 -1099,6 +1124,8 @@@ err_fpga_start
  err_fw_tracer:
        mlx5_eq_table_destroy(dev);
  err_eq_table:
 +      mlx5_irq_table_destroy(dev);
 +err_irq_table:
        mlx5_pagealloc_stop(dev);
        mlx5_events_stop(dev);
        mlx5_put_uars_page(dev, dev->priv.uar);
@@@ -1142,7 -1115,6 +1142,7 @@@ static void mlx5_unload(struct mlx5_cor
        mlx5_fpga_device_stop(dev);
        mlx5_fw_tracer_cleanup(dev->tracer);
        mlx5_eq_table_destroy(dev);
 +      mlx5_irq_table_destroy(dev);
        mlx5_pagealloc_stop(dev);
        mlx5_events_stop(dev);
        mlx5_put_uars_page(dev, dev->priv.uar);
diff --combined drivers/nvme/host/rdma.c
@@@ -213,6 -213,11 +213,11 @@@ static struct nvme_rdma_qe *nvme_rdma_a
        if (!ring)
                return NULL;
  
+       /*
+        * Bind the CQEs (post recv buffers) DMA mapping to the RDMA queue
+        * lifetime. It's safe, since any chage in the underlying RDMA device
+        * will issue error recovery and queue re-creation.
+        */
        for (i = 0; i < ib_queue_size; i++) {
                if (nvme_rdma_alloc_qe(ibdev, &ring[i], capsule_size, dir))
                        goto out_free_ring;
@@@ -274,14 -279,9 +279,9 @@@ static int nvme_rdma_create_qp(struct n
  static void nvme_rdma_exit_request(struct blk_mq_tag_set *set,
                struct request *rq, unsigned int hctx_idx)
  {
-       struct nvme_rdma_ctrl *ctrl = set->driver_data;
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
-       int queue_idx = (set == &ctrl->tag_set) ? hctx_idx + 1 : 0;
-       struct nvme_rdma_queue *queue = &ctrl->queues[queue_idx];
-       struct nvme_rdma_device *dev = queue->device;
  
-       nvme_rdma_free_qe(dev->dev, &req->sqe, sizeof(struct nvme_command),
-                       DMA_TO_DEVICE);
+       kfree(req->sqe.data);
  }
  
  static int nvme_rdma_init_request(struct blk_mq_tag_set *set,
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
        int queue_idx = (set == &ctrl->tag_set) ? hctx_idx + 1 : 0;
        struct nvme_rdma_queue *queue = &ctrl->queues[queue_idx];
-       struct nvme_rdma_device *dev = queue->device;
-       struct ib_device *ibdev = dev->dev;
-       int ret;
  
        nvme_req(rq)->ctrl = &ctrl->ctrl;
-       ret = nvme_rdma_alloc_qe(ibdev, &req->sqe, sizeof(struct nvme_command),
-                       DMA_TO_DEVICE);
-       if (ret)
-               return ret;
+       req->sqe.data = kzalloc(sizeof(struct nvme_command), GFP_KERNEL);
+       if (!req->sqe.data)
+               return -ENOMEM;
  
        req->queue = queue;
  
@@@ -486,7 -482,7 +482,7 @@@ static int nvme_rdma_create_queue_ib(st
        ret = ib_mr_pool_init(queue->qp, &queue->qp->rdma_mrs,
                              queue->queue_size,
                              IB_MR_TYPE_MEM_REG,
 -                            nvme_rdma_get_max_fr_pages(ibdev));
 +                            nvme_rdma_get_max_fr_pages(ibdev), 0);
        if (ret) {
                dev_err(queue->ctrl->ctrl.device,
                        "failed to initialize MR pool sized %d for QID %d\n",
@@@ -641,34 -637,16 +637,16 @@@ static int nvme_rdma_alloc_io_queues(st
  {
        struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
        struct ib_device *ibdev = ctrl->device->dev;
-       unsigned int nr_io_queues;
+       unsigned int nr_io_queues, nr_default_queues;
+       unsigned int nr_read_queues, nr_poll_queues;
        int i, ret;
  
-       nr_io_queues = min(opts->nr_io_queues, num_online_cpus());
-       /*
-        * we map queues according to the device irq vectors for
-        * optimal locality so we don't need more queues than
-        * completion vectors.
-        */
-       nr_io_queues = min_t(unsigned int, nr_io_queues,
-                               ibdev->num_comp_vectors);
-       if (opts->nr_write_queues) {
-               ctrl->io_queues[HCTX_TYPE_DEFAULT] =
-                               min(opts->nr_write_queues, nr_io_queues);
-               nr_io_queues += ctrl->io_queues[HCTX_TYPE_DEFAULT];
-       } else {
-               ctrl->io_queues[HCTX_TYPE_DEFAULT] = nr_io_queues;
-       }
-       ctrl->io_queues[HCTX_TYPE_READ] = nr_io_queues;
-       if (opts->nr_poll_queues) {
-               ctrl->io_queues[HCTX_TYPE_POLL] =
-                       min(opts->nr_poll_queues, num_online_cpus());
-               nr_io_queues += ctrl->io_queues[HCTX_TYPE_POLL];
-       }
+       nr_read_queues = min_t(unsigned int, ibdev->num_comp_vectors,
+                               min(opts->nr_io_queues, num_online_cpus()));
+       nr_default_queues =  min_t(unsigned int, ibdev->num_comp_vectors,
+                               min(opts->nr_write_queues, num_online_cpus()));
+       nr_poll_queues = min(opts->nr_poll_queues, num_online_cpus());
+       nr_io_queues = nr_read_queues + nr_default_queues + nr_poll_queues;
  
        ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
        if (ret)
        dev_info(ctrl->ctrl.device,
                "creating %d I/O queues.\n", nr_io_queues);
  
+       if (opts->nr_write_queues && nr_read_queues < nr_io_queues) {
+               /*
+                * separate read/write queues
+                * hand out dedicated default queues only after we have
+                * sufficient read queues.
+                */
+               ctrl->io_queues[HCTX_TYPE_READ] = nr_read_queues;
+               nr_io_queues -= ctrl->io_queues[HCTX_TYPE_READ];
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] =
+                       min(nr_default_queues, nr_io_queues);
+               nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       } else {
+               /*
+                * shared read/write queues
+                * either no write queues were requested, or we don't have
+                * sufficient queue count to have dedicated default queues.
+                */
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] =
+                       min(nr_read_queues, nr_io_queues);
+               nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       }
+       if (opts->nr_poll_queues && nr_io_queues) {
+               /* map dedicated poll queues only if we have queues left */
+               ctrl->io_queues[HCTX_TYPE_POLL] =
+                       min(nr_poll_queues, nr_io_queues);
+       }
        for (i = 1; i < ctrl->ctrl.queue_count; i++) {
                ret = nvme_rdma_alloc_queue(ctrl, i,
                                ctrl->ctrl.sqsize + 1);
@@@ -769,6 -775,11 +775,11 @@@ static int nvme_rdma_configure_admin_qu
  
        ctrl->max_fr_pages = nvme_rdma_get_max_fr_pages(ctrl->device->dev);
  
+       /*
+        * Bind the async event SQE DMA mapping to the admin queue lifetime.
+        * It's safe, since any chage in the underlying RDMA device will issue
+        * error recovery and queue re-creation.
+        */
        error = nvme_rdma_alloc_qe(ctrl->device->dev, &ctrl->async_event_sqe,
                        sizeof(struct nvme_command), DMA_TO_DEVICE);
        if (error)
@@@ -1709,12 -1720,20 +1720,20 @@@ static blk_status_t nvme_rdma_queue_rq(
                return nvmf_fail_nonready_command(&queue->ctrl->ctrl, rq);
  
        dev = queue->device->dev;
+       req->sqe.dma = ib_dma_map_single(dev, req->sqe.data,
+                                        sizeof(struct nvme_command),
+                                        DMA_TO_DEVICE);
+       err = ib_dma_mapping_error(dev, req->sqe.dma);
+       if (unlikely(err))
+               return BLK_STS_RESOURCE;
        ib_dma_sync_single_for_cpu(dev, sqe->dma,
                        sizeof(struct nvme_command), DMA_TO_DEVICE);
  
        ret = nvme_setup_cmd(ns, rq, c);
        if (ret)
-               return ret;
+               goto unmap_qe;
  
        blk_mq_start_request(rq);
  
        }
  
        return BLK_STS_OK;
  err:
        if (err == -ENOMEM || err == -EAGAIN)
-               return BLK_STS_RESOURCE;
-       return BLK_STS_IOERR;
+               ret = BLK_STS_RESOURCE;
+       else
+               ret = BLK_STS_IOERR;
+ unmap_qe:
+       ib_dma_unmap_single(dev, req->sqe.dma, sizeof(struct nvme_command),
+                           DMA_TO_DEVICE);
+       return ret;
  }
  
  static int nvme_rdma_poll(struct blk_mq_hw_ctx *hctx)
  static void nvme_rdma_complete_rq(struct request *rq)
  {
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+       struct nvme_rdma_queue *queue = req->queue;
+       struct ib_device *ibdev = queue->device->dev;
  
-       nvme_rdma_unmap_data(req->queue, rq);
+       nvme_rdma_unmap_data(queue, rq);
+       ib_dma_unmap_single(ibdev, req->sqe.dma, sizeof(struct nvme_command),
+                           DMA_TO_DEVICE);
        nvme_complete_rq(rq);
  }
  
  static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
  {
        struct nvme_rdma_ctrl *ctrl = set->driver_data;
+       struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
  
-       set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
-       set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
-       set->map[HCTX_TYPE_READ].nr_queues = ctrl->io_queues[HCTX_TYPE_READ];
-       if (ctrl->ctrl.opts->nr_write_queues) {
+       if (opts->nr_write_queues && ctrl->io_queues[HCTX_TYPE_READ]) {
                /* separate read/write queues */
+               set->map[HCTX_TYPE_DEFAULT].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
+               set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
+               set->map[HCTX_TYPE_READ].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_READ];
                set->map[HCTX_TYPE_READ].queue_offset =
-                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
        } else {
-               /* mixed read/write queues */
+               /* shared read/write queues */
+               set->map[HCTX_TYPE_DEFAULT].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
+               set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
+               set->map[HCTX_TYPE_READ].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
                set->map[HCTX_TYPE_READ].queue_offset = 0;
        }
        blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_DEFAULT],
        blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_READ],
                        ctrl->device->dev, 0);
  
-       if (ctrl->ctrl.opts->nr_poll_queues) {
+       if (opts->nr_poll_queues && ctrl->io_queues[HCTX_TYPE_POLL]) {
+               /* map dedicated poll queues only if we have queues left */
                set->map[HCTX_TYPE_POLL].nr_queues =
                                ctrl->io_queues[HCTX_TYPE_POLL];
                set->map[HCTX_TYPE_POLL].queue_offset =
-                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
-               if (ctrl->ctrl.opts->nr_write_queues)
-                       set->map[HCTX_TYPE_POLL].queue_offset +=
-                               ctrl->io_queues[HCTX_TYPE_READ];
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT] +
+                       ctrl->io_queues[HCTX_TYPE_READ];
                blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
        }
+       dev_info(ctrl->ctrl.device,
+               "mapped %d/%d/%d default/read/poll queues.\n",
+               ctrl->io_queues[HCTX_TYPE_DEFAULT],
+               ctrl->io_queues[HCTX_TYPE_READ],
+               ctrl->io_queues[HCTX_TYPE_POLL]);
        return 0;
  }
  
@@@ -7,7 -7,6 +7,7 @@@
  #define _MLX5_ESWITCH_
  
  #include <linux/mlx5/driver.h>
 +#include <net/devlink.h>
  
  #define MLX5_ESWITCH_MANAGER(mdev) MLX5_CAP_GEN(mdev, eswitch_manager)
  
@@@ -30,19 -29,17 +30,19 @@@ enum 
  };
  
  struct mlx5_eswitch_rep;
 -struct mlx5_eswitch_rep_if {
 -      int                    (*load)(struct mlx5_core_dev *dev,
 -                                     struct mlx5_eswitch_rep *rep);
 -      void                   (*unload)(struct mlx5_eswitch_rep *rep);
 -      void                   *(*get_proto_dev)(struct mlx5_eswitch_rep *rep);
 -      void                    *priv;
 -      atomic_t                state;
 +struct mlx5_eswitch_rep_ops {
 +      int (*load)(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep);
 +      void (*unload)(struct mlx5_eswitch_rep *rep);
 +      void *(*get_proto_dev)(struct mlx5_eswitch_rep *rep);
 +};
 +
 +struct mlx5_eswitch_rep_data {
 +      void *priv;
 +      atomic_t state;
  };
  
  struct mlx5_eswitch_rep {
 -      struct mlx5_eswitch_rep_if rep_if[NUM_REP_TYPES];
 +      struct mlx5_eswitch_rep_data rep_data[NUM_REP_TYPES];
        u16                    vport;
        u8                     hw_id[ETH_ALEN];
        u16                    vlan;
  };
  
  void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw,
 -                                    struct mlx5_eswitch_rep_if *rep_if,
 +                                    const struct mlx5_eswitch_rep_ops *ops,
                                      u8 rep_type);
  void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type);
  void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw,
-                                int vport,
+                                u16 vport_num,
                                 u8 rep_type);
  struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw,
-                                               int vport);
+                                               u16 vport_num);
  void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type);
  u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw);
  struct mlx5_flow_handle *
  mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw,
-                                   int vport, u32 sqn);
+                                   u16 vport_num, u32 sqn);
 +
 +#ifdef CONFIG_MLX5_ESWITCH
 +enum devlink_eswitch_encap_mode
 +mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev);
 +#else  /* CONFIG_MLX5_ESWITCH */
 +static inline enum devlink_eswitch_encap_mode
 +mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
 +{
 +      return DEVLINK_ESWITCH_ENCAP_MODE_NONE;
 +}
 +#endif /* CONFIG_MLX5_ESWITCH */
  #endif
diff --combined include/net/devlink.h
@@@ -1,12 -1,8 +1,8 @@@
+ /* SPDX-License-Identifier: GPL-2.0-or-later */
  /*
   * include/net/devlink.h - Network physical device Netlink interface
   * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
   * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
   */
  #ifndef _NET_DEVLINK_H_
  #define _NET_DEVLINK_H_
@@@ -530,10 -526,8 +526,10 @@@ struct devlink_ops 
        int (*eswitch_inline_mode_get)(struct devlink *devlink, u8 *p_inline_mode);
        int (*eswitch_inline_mode_set)(struct devlink *devlink, u8 inline_mode,
                                       struct netlink_ext_ack *extack);
 -      int (*eswitch_encap_mode_get)(struct devlink *devlink, u8 *p_encap_mode);
 -      int (*eswitch_encap_mode_set)(struct devlink *devlink, u8 encap_mode,
 +      int (*eswitch_encap_mode_get)(struct devlink *devlink,
 +                                    enum devlink_eswitch_encap_mode *p_encap_mode);
 +      int (*eswitch_encap_mode_set)(struct devlink *devlink,
 +                                    enum devlink_eswitch_encap_mode encap_mode,
                                      struct netlink_ext_ack *extack);
        int (*info_get)(struct devlink *devlink, struct devlink_info_req *req,
                        struct netlink_ext_ack *extack);
diff --combined include/rdma/ib_verbs.h
@@@ -63,7 -63,6 +63,7 @@@
  #include <linux/preempt.h>
  #include <uapi/rdma/ib_user_verbs.h>
  #include <rdma/restrack.h>
 +#include <rdma/signature.h>
  #include <uapi/rdma/rdma_user_ioctl.h>
  #include <uapi/rdma/ib_user_ioctl_verbs.h>
  
@@@ -133,6 -132,17 +133,6 @@@ struct ib_gid_attr 
        u8                      port_num;
  };
  
 -enum rdma_node_type {
 -      /* IB values map to NodeInfo:NodeType. */
 -      RDMA_NODE_IB_CA         = 1,
 -      RDMA_NODE_IB_SWITCH,
 -      RDMA_NODE_IB_ROUTER,
 -      RDMA_NODE_RNIC,
 -      RDMA_NODE_USNIC,
 -      RDMA_NODE_USNIC_UDP,
 -      RDMA_NODE_UNSPECIFIED,
 -};
 -
  enum {
        /* set the local administered indication */
        IB_SA_WELL_KNOWN_GUID   = BIT_ULL(57) | 2,
@@@ -154,7 -164,7 +154,7 @@@ enum rdma_protocol_type 
  };
  
  __attribute_const__ enum rdma_transport_type
 -rdma_node_get_transport(enum rdma_node_type node_type);
 +rdma_node_get_transport(unsigned int node_type);
  
  enum rdma_network_type {
        RDMA_NETWORK_IB,
@@@ -253,7 -263,7 +253,7 @@@ enum ib_device_cap_flags 
         */
        IB_DEVICE_CROSS_CHANNEL                 = (1 << 27),
        IB_DEVICE_MANAGED_FLOW_STEERING         = (1 << 29),
 -      IB_DEVICE_SIGNATURE_HANDOVER            = (1 << 30),
 +      IB_DEVICE_INTEGRITY_HANDOVER            = (1 << 30),
        IB_DEVICE_ON_DEMAND_PAGING              = (1ULL << 31),
        IB_DEVICE_SG_GAPS_REG                   = (1ULL << 32),
        IB_DEVICE_VIRTUAL_FUNCTION              = (1ULL << 33),
        IB_DEVICE_ALLOW_USER_UNREG              = (1ULL << 37),
  };
  
 -enum ib_signature_prot_cap {
 -      IB_PROT_T10DIF_TYPE_1 = 1,
 -      IB_PROT_T10DIF_TYPE_2 = 1 << 1,
 -      IB_PROT_T10DIF_TYPE_3 = 1 << 2,
 -};
 -
 -enum ib_signature_guard_cap {
 -      IB_GUARD_T10DIF_CRC     = 1,
 -      IB_GUARD_T10DIF_CSUM    = 1 << 1,
 -};
 -
  enum ib_atomic_cap {
        IB_ATOMIC_NONE,
        IB_ATOMIC_HCA,
@@@ -390,7 -411,6 +390,7 @@@ struct ib_device_attr 
        int                     max_srq_wr;
        int                     max_srq_sge;
        unsigned int            max_fast_reg_page_list_len;
 +      unsigned int            max_pi_fast_reg_page_list_len;
        u16                     max_pkeys;
        u8                      local_ca_ack_delay;
        int                     sig_prot_cap;
@@@ -776,26 -796,118 +776,26 @@@ __attribute_const__ int ib_rate_to_mbps
   * enum ib_mr_type - memory region type
   * @IB_MR_TYPE_MEM_REG:       memory region that is used for
   *                            normal registration
 - * @IB_MR_TYPE_SIGNATURE:     memory region that is used for
 - *                            signature operations (data-integrity
 - *                            capable regions)
   * @IB_MR_TYPE_SG_GAPS:       memory region that is capable to
   *                            register any arbitrary sg lists (without
   *                            the normal mr constraints - see
   *                            ib_map_mr_sg)
 + * @IB_MR_TYPE_DM:            memory region that is used for device
 + *                            memory registration
 + * @IB_MR_TYPE_USER:          memory region that is used for the user-space
 + *                            application
 + * @IB_MR_TYPE_DMA:           memory region that is used for DMA operations
 + *                            without address translations (VA=PA)
 + * @IB_MR_TYPE_INTEGRITY:     memory region that is used for
 + *                            data integrity operations
   */
  enum ib_mr_type {
        IB_MR_TYPE_MEM_REG,
 -      IB_MR_TYPE_SIGNATURE,
        IB_MR_TYPE_SG_GAPS,
 -};
 -
 -/**
 - * Signature types
 - * IB_SIG_TYPE_NONE: Unprotected.
 - * IB_SIG_TYPE_T10_DIF: Type T10-DIF
 - */
 -enum ib_signature_type {
 -      IB_SIG_TYPE_NONE,
 -      IB_SIG_TYPE_T10_DIF,
 -};
 -
 -/**
 - * Signature T10-DIF block-guard types
 - * IB_T10DIF_CRC: Corresponds to T10-PI mandated CRC checksum rules.
 - * IB_T10DIF_CSUM: Corresponds to IP checksum rules.
 - */
 -enum ib_t10_dif_bg_type {
 -      IB_T10DIF_CRC,
 -      IB_T10DIF_CSUM
 -};
 -
 -/**
 - * struct ib_t10_dif_domain - Parameters specific for T10-DIF
 - *     domain.
 - * @bg_type: T10-DIF block guard type (CRC|CSUM)
 - * @pi_interval: protection information interval.
 - * @bg: seed of guard computation.
 - * @app_tag: application tag of guard block
 - * @ref_tag: initial guard block reference tag.
 - * @ref_remap: Indicate wethear the reftag increments each block
 - * @app_escape: Indicate to skip block check if apptag=0xffff
 - * @ref_escape: Indicate to skip block check if reftag=0xffffffff
 - * @apptag_check_mask: check bitmask of application tag.
 - */
 -struct ib_t10_dif_domain {
 -      enum ib_t10_dif_bg_type bg_type;
 -      u16                     pi_interval;
 -      u16                     bg;
 -      u16                     app_tag;
 -      u32                     ref_tag;
 -      bool                    ref_remap;
 -      bool                    app_escape;
 -      bool                    ref_escape;
 -      u16                     apptag_check_mask;
 -};
 -
 -/**
 - * struct ib_sig_domain - Parameters for signature domain
 - * @sig_type: specific signauture type
 - * @sig: union of all signature domain attributes that may
 - *     be used to set domain layout.
 - */
 -struct ib_sig_domain {
 -      enum ib_signature_type sig_type;
 -      union {
 -              struct ib_t10_dif_domain dif;
 -      } sig;
 -};
 -
 -/**
 - * struct ib_sig_attrs - Parameters for signature handover operation
 - * @check_mask: bitmask for signature byte check (8 bytes)
 - * @mem: memory domain layout desciptor.
 - * @wire: wire domain layout desciptor.
 - */
 -struct ib_sig_attrs {
 -      u8                      check_mask;
 -      struct ib_sig_domain    mem;
 -      struct ib_sig_domain    wire;
 -};
 -
 -enum ib_sig_err_type {
 -      IB_SIG_BAD_GUARD,
 -      IB_SIG_BAD_REFTAG,
 -      IB_SIG_BAD_APPTAG,
 -};
 -
 -/**
 - * Signature check masks (8 bytes in total) according to the T10-PI standard:
 - *  -------- -------- ------------
 - * | GUARD  | APPTAG |   REFTAG   |
 - * |  2B    |  2B    |    4B      |
 - *  -------- -------- ------------
 - */
 -enum {
 -      IB_SIG_CHECK_GUARD      = 0xc0,
 -      IB_SIG_CHECK_APPTAG     = 0x30,
 -      IB_SIG_CHECK_REFTAG     = 0x0f,
 -};
 -
 -/**
 - * struct ib_sig_err - signature error descriptor
 - */
 -struct ib_sig_err {
 -      enum ib_sig_err_type    err_type;
 -      u32                     expected;
 -      u32                     actual;
 -      u64                     sig_err_offset;
 -      u32                     key;
 +      IB_MR_TYPE_DM,
 +      IB_MR_TYPE_USER,
 +      IB_MR_TYPE_DMA,
 +      IB_MR_TYPE_INTEGRITY,
  };
  
  enum ib_mr_status_check {
@@@ -1052,7 -1164,7 +1052,7 @@@ enum ib_qp_create_flags 
        IB_QP_CREATE_MANAGED_SEND               = 1 << 3,
        IB_QP_CREATE_MANAGED_RECV               = 1 << 4,
        IB_QP_CREATE_NETIF_QP                   = 1 << 5,
 -      IB_QP_CREATE_SIGNATURE_EN               = 1 << 6,
 +      IB_QP_CREATE_INTEGRITY_EN               = 1 << 6,
        /* FREE                                 = 1 << 7, */
        IB_QP_CREATE_SCATTER_FCS                = 1 << 8,
        IB_QP_CREATE_CVLAN_STRIPPING            = 1 << 9,
@@@ -1231,7 -1343,7 +1231,7 @@@ enum ib_wr_opcode 
  
        /* These are kernel only and can not be issued by userspace */
        IB_WR_REG_MR = 0x20,
 -      IB_WR_REG_SIG_MR,
 +      IB_WR_REG_MR_INTEGRITY,
  
        /* reserve values for low level drivers' internal use.
         * These values will not be used at all in the ib core layer.
@@@ -1341,6 -1453,20 +1341,6 @@@ static inline const struct ib_reg_wr *r
        return container_of(wr, struct ib_reg_wr, wr);
  }
  
 -struct ib_sig_handover_wr {
 -      struct ib_send_wr       wr;
 -      struct ib_sig_attrs    *sig_attrs;
 -      struct ib_mr           *sig_mr;
 -      int                     access_flags;
 -      struct ib_sge          *prot;
 -};
 -
 -static inline const struct ib_sig_handover_wr *
 -sig_handover_wr(const struct ib_send_wr *wr)
 -{
 -      return container_of(wr, struct ib_sig_handover_wr, wr);
 -}
 -
  struct ib_recv_wr {
        struct ib_recv_wr      *next;
        union {
@@@ -1692,7 -1818,6 +1692,7 @@@ struct ib_qp 
        struct ib_qp_security  *qp_sec;
        u8                      port;
  
 +      bool                    integrity_en;
        /*
         * Implementation details of the RDMA core, don't use in drivers:
         */
@@@ -1715,7 -1840,6 +1715,7 @@@ struct ib_mr 
        u64                iova;
        u64                length;
        unsigned int       page_size;
 +      enum ib_mr_type    type;
        bool               need_inval;
        union {
                struct ib_uobject       *uobject;       /* user */
        };
  
        struct ib_dm      *dm;
 -
 +      struct ib_sig_attrs *sig_attrs; /* only for IB_MR_TYPE_INTEGRITY MRs */
        /*
         * Implementation details of the RDMA core, don't use in drivers:
         */
@@@ -2205,11 -2329,6 +2205,11 @@@ struct iw_cm_conn_param
   * need to define the supported operations, otherwise they will be set to null.
   */
  struct ib_device_ops {
 +      struct module *owner;
 +      enum rdma_driver_id driver_id;
 +      u32 uverbs_abi_ver;
 +      unsigned int uverbs_no_driver_id_binding:1;
 +
        int (*post_send)(struct ib_qp *qp, const struct ib_send_wr *send_wr,
                         const struct ib_send_wr **bad_send_wr);
        int (*post_recv)(struct ib_qp *qp, const struct ib_recv_wr *recv_wr,
        int (*query_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
                        int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
        int (*destroy_qp)(struct ib_qp *qp, struct ib_udata *udata);
 -      struct ib_cq *(*create_cq)(struct ib_device *device,
 -                                 const struct ib_cq_init_attr *attr,
 -                                 struct ib_udata *udata);
 +      int (*create_cq)(struct ib_cq *cq, const struct ib_cq_init_attr *attr,
 +                       struct ib_udata *udata);
        int (*modify_cq)(struct ib_cq *cq, u16 cq_count, u16 cq_period);
 -      int (*destroy_cq)(struct ib_cq *cq, struct ib_udata *udata);
 +      void (*destroy_cq)(struct ib_cq *cq, struct ib_udata *udata);
        int (*resize_cq)(struct ib_cq *cq, int cqe, struct ib_udata *udata);
        struct ib_mr *(*get_dma_mr)(struct ib_pd *pd, int mr_access_flags);
        struct ib_mr *(*reg_user_mr)(struct ib_pd *pd, u64 start, u64 length,
        int (*dereg_mr)(struct ib_mr *mr, struct ib_udata *udata);
        struct ib_mr *(*alloc_mr)(struct ib_pd *pd, enum ib_mr_type mr_type,
                                  u32 max_num_sg, struct ib_udata *udata);
 +      struct ib_mr *(*alloc_mr_integrity)(struct ib_pd *pd,
 +                                          u32 max_num_data_sg,
 +                                          u32 max_num_meta_sg);
        int (*advise_mr)(struct ib_pd *pd,
                         enum ib_uverbs_advise_mr_advice advice, u32 flags,
                         struct ib_sge *sg_list, u32 num_sge,
        struct ib_wq *(*create_wq)(struct ib_pd *pd,
                                   struct ib_wq_init_attr *init_attr,
                                   struct ib_udata *udata);
 -      int (*destroy_wq)(struct ib_wq *wq, struct ib_udata *udata);
 +      void (*destroy_wq)(struct ib_wq *wq, struct ib_udata *udata);
        int (*modify_wq)(struct ib_wq *wq, struct ib_wq_attr *attr,
                         u32 wq_attr_mask, struct ib_udata *udata);
        struct ib_rwq_ind_table *(*create_rwq_ind_table)(
        int (*read_counters)(struct ib_counters *counters,
                             struct ib_counters_read_attr *counters_read_attr,
                             struct uverbs_attr_bundle *attrs);
 +      int (*map_mr_sg_pi)(struct ib_mr *mr, struct scatterlist *data_sg,
 +                          int data_sg_nents, unsigned int *data_sg_offset,
 +                          struct scatterlist *meta_sg, int meta_sg_nents,
 +                          unsigned int *meta_sg_offset);
 +
        /**
         * alloc_hw_stats - Allocate a struct rdma_hw_stats and fill in the
         *   driver initialized data.  The struct is kfree()'ed by the sysfs
        int (*iw_destroy_listen)(struct iw_cm_id *cm_id);
  
        DECLARE_RDMA_OBJ_SIZE(ib_ah);
 +      DECLARE_RDMA_OBJ_SIZE(ib_cq);
        DECLARE_RDMA_OBJ_SIZE(ib_pd);
        DECLARE_RDMA_OBJ_SIZE(ib_srq);
        DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
@@@ -2525,6 -2636,7 +2525,6 @@@ struct ib_device 
  
        int                           num_comp_vectors;
  
 -      struct module               *owner;
        union {
                struct device           dev;
                struct ib_core_device   coredev;
         */
        const struct attribute_group    *groups[3];
  
 -      int                          uverbs_abi_ver;
        u64                          uverbs_cmd_mask;
        u64                          uverbs_ex_cmd_mask;
  
        struct rdma_restrack_root *res;
  
        const struct uapi_definition   *driver_def;
 -      enum rdma_driver_id             driver_id;
  
        /*
         * Positive refcount indicates that the device is currently
        u32 iw_driver_flags;
  };
  
 +struct ib_client_nl_info;
  struct ib_client {
        const char *name;
        void (*add)   (struct ib_device *);
        void (*remove)(struct ib_device *, void *client_data);
+       void (*rename)(struct ib_device *dev, void *client_data);
 +      int (*get_nl_info)(struct ib_device *ibdev, void *client_data,
 +                         struct ib_client_nl_info *res);
 +      int (*get_global_nl_info)(struct ib_client_nl_info *res);
  
        /* Returns the net_dev belonging to this ib_client and matching the
         * given parameters.
@@@ -3748,9 -3859,9 +3749,9 @@@ int ib_destroy_cq_user(struct ib_cq *cq
   *
   * NOTE: for user cq use ib_destroy_cq_user with valid udata!
   */
 -static inline int ib_destroy_cq(struct ib_cq *cq)
 +static inline void ib_destroy_cq(struct ib_cq *cq)
  {
 -      return ib_destroy_cq_user(cq, NULL);
 +      ib_destroy_cq_user(cq, NULL);
  }
  
  /**
@@@ -4037,10 -4148,6 +4038,10 @@@ static inline struct ib_mr *ib_alloc_mr
        return ib_alloc_mr_user(pd, mr_type, max_num_sg, NULL);
  }
  
 +struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd,
 +                                  u32 max_num_data_sg,
 +                                  u32 max_num_meta_sg);
 +
  /**
   * ib_update_fast_reg_key - updates the key portion of the fast_reg MR
   *   R_Key and L_Key.
@@@ -4225,10 -4332,6 +4226,10 @@@ int ib_destroy_rwq_ind_table(struct ib_
  
  int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
                 unsigned int *sg_offset, unsigned int page_size);
 +int ib_map_mr_sg_pi(struct ib_mr *mr, struct scatterlist *data_sg,
 +                  int data_sg_nents, unsigned int *data_sg_offset,
 +                  struct scatterlist *meta_sg, int meta_sg_nents,
 +                  unsigned int *meta_sg_offset, unsigned int page_size);
  
  static inline int
  ib_map_mr_sg_zbva(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
diff --combined include/rdma/mr_pool.h
@@@ -1,14 -1,6 +1,6 @@@
+ /* SPDX-License-Identifier: GPL-2.0-only */
  /*
   * Copyright (c) 2016 HGST, a Western Digital Company.
-  *
-  * This program is free software; you can redistribute it and/or modify it
-  * under the terms and conditions of the GNU General Public License,
-  * version 2, as published by the Free Software Foundation.
-  *
-  * This program is distributed in the hope it will be useful, but WITHOUT
-  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  * more details.
   */
  #ifndef _RDMA_MR_POOL_H
  #define _RDMA_MR_POOL_H 1
@@@ -19,7 -11,7 +11,7 @@@ struct ib_mr *ib_mr_pool_get(struct ib_
  void ib_mr_pool_put(struct ib_qp *qp, struct list_head *list, struct ib_mr *mr);
  
  int ib_mr_pool_init(struct ib_qp *qp, struct list_head *list, int nr,
 -              enum ib_mr_type type, u32 max_num_sg);
 +              enum ib_mr_type type, u32 max_num_sg, u32 max_num_meta_sg);
  void ib_mr_pool_destroy(struct ib_qp *qp, struct list_head *list);
  
  #endif /* _RDMA_MR_POOL_H */
diff --combined include/rdma/rw.h
@@@ -1,14 -1,6 +1,6 @@@
+ /* SPDX-License-Identifier: GPL-2.0-only */
  /*
   * Copyright (c) 2016 HGST, a Western Digital Company.
-  *
-  * This program is free software; you can redistribute it and/or modify it
-  * under the terms and conditions of the GNU General Public License,
-  * version 2, as published by the Free Software Foundation.
-  *
-  * This program is distributed in the hope it will be useful, but WITHOUT
-  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  * more details.
   */
  #ifndef _RDMA_RW_H
  #define _RDMA_RW_H
@@@ -47,6 -39,15 +39,6 @@@ struct rdma_rw_ctx 
                        struct ib_send_wr       inv_wr;
                        struct ib_mr            *mr;
                } *reg;
 -
 -              struct {
 -                      struct rdma_rw_reg_ctx  data;
 -                      struct rdma_rw_reg_ctx  prot;
 -                      struct ib_send_wr       sig_inv_wr;
 -                      struct ib_mr            *sig_mr;
 -                      struct ib_sge           sig_sge;
 -                      struct ib_sig_handover_wr sig_wr;
 -              } *sig;
        };
  };
  
diff --combined net/core/devlink.c
@@@ -1,14 -1,10 +1,10 @@@
+ // SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * net/core/devlink.c - Network physical/parent device Netlink interface
   *
   * Heavily inspired by net/wireless/
   * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
   * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
   */
  
  #include <linux/kernel.h>
@@@ -1552,8 -1548,7 +1548,8 @@@ static int devlink_nl_eswitch_fill(stru
                                   u32 seq, int flags)
  {
        const struct devlink_ops *ops = devlink->ops;
 -      u8 inline_mode, encap_mode;
 +      enum devlink_eswitch_encap_mode encap_mode;
 +      u8 inline_mode;
        void *hdr;
        int err = 0;
        u16 mode;
@@@ -1629,8 -1624,7 +1625,8 @@@ static int devlink_nl_cmd_eswitch_set_d
  {
        struct devlink *devlink = info->user_ptr[0];
        const struct devlink_ops *ops = devlink->ops;
 -      u8 inline_mode, encap_mode;
 +      enum devlink_eswitch_encap_mode encap_mode;
 +      u8 inline_mode;
        int err = 0;
        u16 mode;