Merge 4491b85480 ("Merge tag 'dma-mapping-6.12-2024-09-24' of git://git.infradead.org/users/hch/dma-mapping") into android-mainline
Steps on the way to 6.12-rc1 Bug: 367265496 Change-Id: Id919259b4ee6b47fdb74f76f16914f07332fb135 Signed-off-by: Matthias Maennich <maennich@google.com>
This commit is contained in:
@@ -316,6 +316,7 @@ Jiri Slaby <jirislaby@kernel.org> <xslaby@fi.muni.cz>
|
||||
Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com>
|
||||
Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
|
||||
Jishnu Prakash <quic_jprakash@quicinc.com> <jprakash@codeaurora.org>
|
||||
Joel Granados <joel.granados@kernel.org> <j.granados@samsung.com>
|
||||
Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
|
||||
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
|
||||
John Crispin <john@phrozen.org> <blogic@openwrt.org>
|
||||
|
||||
@@ -171,6 +171,13 @@ properties:
|
||||
memory types as ratified in the 20191213 version of the privileged
|
||||
ISA specification.
|
||||
|
||||
- const: svvptc
|
||||
description:
|
||||
The standard Svvptc supervisor-level extension for
|
||||
address-translation cache behaviour with respect to invalid entries
|
||||
as ratified at commit 4a69197e5617 ("Update to ratified state") of
|
||||
riscv-svvptc.
|
||||
|
||||
- const: zacas
|
||||
description: |
|
||||
The Zacas extension for Atomic Compare-and-Swap (CAS) instructions
|
||||
|
||||
@@ -83,6 +83,15 @@ The current status of the BPF scheduler can be determined as follows:
|
||||
# cat /sys/kernel/sched_ext/root/ops
|
||||
simple
|
||||
|
||||
You can check if any BPF scheduler has ever been loaded since boot by examining
|
||||
this monotonically incrementing counter (a value of zero indicates that no BPF
|
||||
scheduler has been loaded):
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
# cat /sys/kernel/sched_ext/enable_seq
|
||||
1
|
||||
|
||||
``tools/sched_ext/scx_show_state.py`` is a drgn script which shows more
|
||||
detailed information:
|
||||
|
||||
@@ -96,6 +105,7 @@ detailed information:
|
||||
enable_state : enabled (2)
|
||||
bypass_depth : 0
|
||||
nr_rejected : 0
|
||||
enable_seq : 1
|
||||
|
||||
If ``CONFIG_SCHED_DEBUG`` is set, whether a given task is on sched_ext can
|
||||
be determined as follows:
|
||||
|
||||
@@ -8,7 +8,7 @@ Landlock: unprivileged access control
|
||||
=====================================
|
||||
|
||||
:Author: Mickaël Salaün
|
||||
:Date: July 2024
|
||||
:Date: September 2024
|
||||
|
||||
The goal of Landlock is to enable to restrict ambient rights (e.g. global
|
||||
filesystem or network access) for a set of processes. Because Landlock
|
||||
@@ -81,6 +81,9 @@ to be explicit about the denied-by-default access rights.
|
||||
.handled_access_net =
|
||||
LANDLOCK_ACCESS_NET_BIND_TCP |
|
||||
LANDLOCK_ACCESS_NET_CONNECT_TCP,
|
||||
.scoped =
|
||||
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
|
||||
LANDLOCK_SCOPE_SIGNAL,
|
||||
};
|
||||
|
||||
Because we may not know on which kernel version an application will be
|
||||
@@ -119,6 +122,11 @@ version, and only use the available subset of access rights:
|
||||
case 4:
|
||||
/* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */
|
||||
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;
|
||||
__attribute__((fallthrough));
|
||||
case 5:
|
||||
/* Removes LANDLOCK_SCOPE_* for ABI < 6 */
|
||||
ruleset_attr.scoped &= ~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
|
||||
LANDLOCK_SCOPE_SIGNAL);
|
||||
}
|
||||
|
||||
This enables to create an inclusive ruleset that will contain our rules.
|
||||
@@ -306,6 +314,38 @@ To be allowed to use :manpage:`ptrace(2)` and related syscalls on a target
|
||||
process, a sandboxed process should have a subset of the target process rules,
|
||||
which means the tracee must be in a sub-domain of the tracer.
|
||||
|
||||
IPC scoping
|
||||
-----------
|
||||
|
||||
Similar to the implicit `Ptrace restrictions`_, we may want to further restrict
|
||||
interactions between sandboxes. Each Landlock domain can be explicitly scoped
|
||||
for a set of actions by specifying it on a ruleset. For example, if a
|
||||
sandboxed process should not be able to :manpage:`connect(2)` to a
|
||||
non-sandboxed process through abstract :manpage:`unix(7)` sockets, we can
|
||||
specify such restriction with ``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET``.
|
||||
Moreover, if a sandboxed process should not be able to send a signal to a
|
||||
non-sandboxed process, we can specify this restriction with
|
||||
``LANDLOCK_SCOPE_SIGNAL``.
|
||||
|
||||
A sandboxed process can connect to a non-sandboxed process when its domain is
|
||||
not scoped. If a process's domain is scoped, it can only connect to sockets
|
||||
created by processes in the same scope.
|
||||
Moreover, If a process is scoped to send signal to a non-scoped process, it can
|
||||
only send signals to processes in the same scope.
|
||||
|
||||
A connected datagram socket behaves like a stream socket when its domain is
|
||||
scoped, meaning if the domain is scoped after the socket is connected , it can
|
||||
still :manpage:`send(2)` data just like a stream socket. However, in the same
|
||||
scenario, a non-connected datagram socket cannot send data (with
|
||||
:manpage:`sendto(2)`) outside its scope.
|
||||
|
||||
A process with a scoped domain can inherit a socket created by a non-scoped
|
||||
process. The process cannot connect to this socket since it has a scoped
|
||||
domain.
|
||||
|
||||
IPC scoping does not support exceptions, so if a domain is scoped, no rules can
|
||||
be added to allow access to resources or processes outside of the scope.
|
||||
|
||||
Truncating files
|
||||
----------------
|
||||
|
||||
@@ -404,7 +444,7 @@ Access rights
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: include/uapi/linux/landlock.h
|
||||
:identifiers: fs_access net_access
|
||||
:identifiers: fs_access net_access scope
|
||||
|
||||
Creating a new ruleset
|
||||
----------------------
|
||||
@@ -541,6 +581,20 @@ earlier ABI.
|
||||
Starting with the Landlock ABI version 5, it is possible to restrict the use of
|
||||
:manpage:`ioctl(2)` using the new ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right.
|
||||
|
||||
Abstract UNIX socket scoping (ABI < 6)
|
||||
--------------------------------------
|
||||
|
||||
Starting with the Landlock ABI version 6, it is possible to restrict
|
||||
connections to an abstract :manpage:`unix(7)` socket by setting
|
||||
``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET`` to the ``scoped`` ruleset attribute.
|
||||
|
||||
Signal scoping (ABI < 6)
|
||||
------------------------
|
||||
|
||||
Starting with the Landlock ABI version 6, it is possible to restrict
|
||||
:manpage:`signal(7)` sending by setting ``LANDLOCK_SCOPE_SIGNAL`` to the
|
||||
``scoped`` ruleset attribute.
|
||||
|
||||
.. _kernel_support:
|
||||
|
||||
Kernel support
|
||||
|
||||
+1
-1
@@ -18514,7 +18514,7 @@ F: tools/testing/selftests/proc/
|
||||
PROC SYSCTL
|
||||
M: Luis Chamberlain <mcgrof@kernel.org>
|
||||
M: Kees Cook <kees@kernel.org>
|
||||
M: Joel Granados <j.granados@samsung.com>
|
||||
M: Joel Granados <joel.granados@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
@@ -138,7 +138,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
pr_debug("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n",
|
||||
_stext, _etext, _sdata, _edata, __bss_start, __bss_stop);
|
||||
pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ",
|
||||
pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n",
|
||||
__bss_stop, memory_start, memory_start, memory_end);
|
||||
|
||||
memblock_add(_rambase, memory_end - _rambase);
|
||||
|
||||
@@ -107,6 +107,7 @@ config CRYPTO_AES_PPC_SPE
|
||||
|
||||
config CRYPTO_AES_GCM_P10
|
||||
tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)"
|
||||
depends on BROKEN
|
||||
depends on PPC64 && CPU_LITTLE_ENDIAN && VSX
|
||||
select CRYPTO_LIB_AES
|
||||
select CRYPTO_ALGAPI
|
||||
|
||||
@@ -70,6 +70,7 @@ config RISCV
|
||||
select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
|
||||
select ARCH_USE_MEMTEST
|
||||
select ARCH_USE_QUEUED_RWLOCKS
|
||||
select ARCH_USE_SYM_ANNOTATIONS
|
||||
select ARCH_USES_CFI_TRAPS if CFI_CLANG
|
||||
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if MMU
|
||||
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
|
||||
@@ -94,6 +95,7 @@ config RISCV
|
||||
select GENERIC_ATOMIC64 if !64BIT
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
|
||||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_CPU_VULNERABILITIES
|
||||
select GENERIC_EARLY_IOREMAP
|
||||
select GENERIC_ENTRY
|
||||
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
|
||||
@@ -204,6 +206,7 @@ config RISCV
|
||||
select THREAD_INFO_IN_TASK
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select UACCESS_MEMCPY if !MMU
|
||||
select USER_STACKTRACE_SUPPORT
|
||||
select ZONE_DMA32 if 64BIT
|
||||
|
||||
config CLANG_SUPPORTS_DYNAMIC_FTRACE
|
||||
@@ -323,6 +326,11 @@ config GENERIC_HWEIGHT
|
||||
config FIX_EARLYCON_MEM
|
||||
def_bool MMU
|
||||
|
||||
config ILLEGAL_POINTER_VALUE
|
||||
hex
|
||||
default 0 if 32BIT
|
||||
default 0xdead000000000000 if 64BIT
|
||||
|
||||
config PGTABLE_LEVELS
|
||||
int
|
||||
default 5 if 64BIT
|
||||
|
||||
@@ -137,12 +137,10 @@ CONFIG_VIRTIO_NET=y
|
||||
CONFIG_MACB=y
|
||||
CONFIG_E1000E=y
|
||||
CONFIG_R8169=y
|
||||
CONFIG_RAVB=y
|
||||
CONFIG_STMMAC_ETH=m
|
||||
CONFIG_MICREL_PHY=y
|
||||
CONFIG_MICROSEMI_PHY=y
|
||||
CONFIG_MOTORCOMM_PHY=y
|
||||
CONFIG_CAN_RCAR_CANFD=m
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_KEYBOARD_SUN4I_LRADC=m
|
||||
CONFIG_SERIAL_8250=y
|
||||
@@ -150,7 +148,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_VIRTIO=y
|
||||
@@ -160,11 +157,9 @@ CONFIG_I2C_CHARDEV=m
|
||||
CONFIG_I2C_DESIGNWARE_CORE=y
|
||||
CONFIG_I2C_DESIGNWARE_PLATFORM=y
|
||||
CONFIG_I2C_MV64XXX=m
|
||||
CONFIG_I2C_RIIC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_CADENCE_QUADSPI=m
|
||||
CONFIG_SPI_PL022=m
|
||||
CONFIG_SPI_RSPI=m
|
||||
CONFIG_SPI_SIFIVE=y
|
||||
CONFIG_SPI_SUN6I=y
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
@@ -177,7 +172,6 @@ CONFIG_POWER_RESET_GPIO_RESTART=y
|
||||
CONFIG_SENSORS_SFCTEMP=m
|
||||
CONFIG_CPU_THERMAL=y
|
||||
CONFIG_DEVFREQ_THERMAL=y
|
||||
CONFIG_RZG2L_THERMAL=y
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_SUNXI_WATCHDOG=y
|
||||
CONFIG_MFD_AXP20X_I2C=y
|
||||
@@ -206,11 +200,11 @@ CONFIG_USB=y
|
||||
CONFIG_USB_OTG=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_PLATFORM=y
|
||||
# CONFIG_USB_XHCI_RCAR is not set
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_RENESAS_USBHS=m
|
||||
CONFIG_USB_STORAGE=y
|
||||
CONFIG_USB_UAS=y
|
||||
CONFIG_USB_CDNS_SUPPORT=m
|
||||
@@ -222,7 +216,6 @@ CONFIG_USB_MUSB_HDRC=m
|
||||
CONFIG_USB_MUSB_SUNXI=m
|
||||
CONFIG_NOP_USB_XCEIV=m
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_RENESAS_USBHS_UDC=m
|
||||
CONFIG_USB_CONFIGFS=m
|
||||
CONFIG_USB_CONFIGFS_SERIAL=y
|
||||
CONFIG_USB_CONFIGFS_ACM=y
|
||||
@@ -240,7 +233,6 @@ CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
|
||||
CONFIG_MMC_SDHCI_CADENCE=y
|
||||
CONFIG_MMC_SPI=y
|
||||
CONFIG_MMC_SDHI=y
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_STARFIVE=y
|
||||
CONFIG_MMC_SUNXI=y
|
||||
@@ -258,7 +250,6 @@ CONFIG_CLK_SOPHGO_SG2042_PLL=y
|
||||
CONFIG_CLK_SOPHGO_SG2042_CLKGEN=y
|
||||
CONFIG_CLK_SOPHGO_SG2042_RPGATE=y
|
||||
CONFIG_SUN8I_DE2_CCU=m
|
||||
CONFIG_RENESAS_OSTM=y
|
||||
CONFIG_SUN50I_IOMMU=y
|
||||
CONFIG_RPMSG_CHAR=y
|
||||
CONFIG_RPMSG_CTRL=y
|
||||
@@ -266,7 +257,6 @@ CONFIG_RPMSG_VIRTIO=y
|
||||
CONFIG_PM_DEVFREQ=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_PHY_SUN4I_USB=m
|
||||
CONFIG_PHY_RCAR_GEN3_USB2=y
|
||||
CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=m
|
||||
CONFIG_PHY_STARFIVE_JH7110_PCIE=m
|
||||
CONFIG_PHY_STARFIVE_JH7110_USB=m
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
1:
|
||||
.endm
|
||||
|
||||
ENTRY(sifive_cip_453_page_fault_trp)
|
||||
SYM_FUNC_START(sifive_cip_453_page_fault_trp)
|
||||
ADD_SIGN_EXT a0, t0, t1
|
||||
#ifdef CONFIG_MMU
|
||||
la t0, do_page_fault
|
||||
@@ -29,10 +29,10 @@ ENTRY(sifive_cip_453_page_fault_trp)
|
||||
la t0, do_trap_unknown
|
||||
#endif
|
||||
jr t0
|
||||
END(sifive_cip_453_page_fault_trp)
|
||||
SYM_FUNC_END(sifive_cip_453_page_fault_trp)
|
||||
|
||||
ENTRY(sifive_cip_453_insn_fault_trp)
|
||||
SYM_FUNC_START(sifive_cip_453_insn_fault_trp)
|
||||
ADD_SIGN_EXT a0, t0, t1
|
||||
la t0, do_trap_insn_fault
|
||||
jr t0
|
||||
END(sifive_cip_453_insn_fault_trp)
|
||||
SYM_FUNC_END(sifive_cip_453_insn_fault_trp)
|
||||
|
||||
@@ -91,10 +91,8 @@ static inline void acpi_get_cbo_block_size(struct acpi_table_header *table,
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
int acpi_numa_get_nid(unsigned int cpu);
|
||||
void acpi_map_cpus_to_nodes(void);
|
||||
#else
|
||||
static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; }
|
||||
static inline void acpi_map_cpus_to_nodes(void) { }
|
||||
#endif /* CONFIG_ACPI_NUMA */
|
||||
|
||||
|
||||
@@ -222,44 +222,44 @@ legacy:
|
||||
#define __NOT(x) (~(x))
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* arch_test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation may be reordered on other architectures than x86.
|
||||
*/
|
||||
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||
static inline int arch_test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
return __test_and_op_bit(or, __NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* arch_test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation can be reordered on other architectures other than x86.
|
||||
*/
|
||||
static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||
static inline int arch_test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
return __test_and_op_bit(and, __NOT, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its old value
|
||||
* arch_test_and_change_bit - Change a bit and return its old value
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
|
||||
static inline int arch_test_and_change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
return __test_and_op_bit(xor, __NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* arch_set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
@@ -270,13 +270,13 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static inline void set_bit(int nr, volatile unsigned long *addr)
|
||||
static inline void arch_set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
__op_bit(or, __NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* arch_clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
@@ -284,13 +284,13 @@ static inline void set_bit(int nr, volatile unsigned long *addr)
|
||||
* on non x86 architectures, so if you are writing portable code,
|
||||
* make sure not to rely on its reordering guarantees.
|
||||
*/
|
||||
static inline void clear_bit(int nr, volatile unsigned long *addr)
|
||||
static inline void arch_clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
__op_bit(and, __NOT, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* arch_change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
@@ -298,40 +298,40 @@ static inline void clear_bit(int nr, volatile unsigned long *addr)
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static inline void change_bit(int nr, volatile unsigned long *addr)
|
||||
static inline void arch_change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
__op_bit(xor, __NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit_lock - Set a bit and return its old value, for lock
|
||||
* arch_test_and_set_bit_lock - Set a bit and return its old value, for lock
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and provides acquire barrier semantics.
|
||||
* It can be used to implement bit locks.
|
||||
*/
|
||||
static inline int test_and_set_bit_lock(
|
||||
static inline int arch_test_and_set_bit_lock(
|
||||
unsigned long nr, volatile unsigned long *addr)
|
||||
{
|
||||
return __test_and_op_bit_ord(or, __NOP, nr, addr, .aq);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit_unlock - Clear a bit in memory, for unlock
|
||||
* arch_clear_bit_unlock - Clear a bit in memory, for unlock
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This operation is atomic and provides release barrier semantics.
|
||||
*/
|
||||
static inline void clear_bit_unlock(
|
||||
static inline void arch_clear_bit_unlock(
|
||||
unsigned long nr, volatile unsigned long *addr)
|
||||
{
|
||||
__op_bit_ord(and, __NOT, nr, addr, .rl);
|
||||
}
|
||||
|
||||
/**
|
||||
* __clear_bit_unlock - Clear a bit in memory, for unlock
|
||||
* arch___clear_bit_unlock - Clear a bit in memory, for unlock
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
@@ -345,13 +345,13 @@ static inline void clear_bit_unlock(
|
||||
* non-atomic property here: it's a lot more instructions and we still have to
|
||||
* provide release semantics anyway.
|
||||
*/
|
||||
static inline void __clear_bit_unlock(
|
||||
static inline void arch___clear_bit_unlock(
|
||||
unsigned long nr, volatile unsigned long *addr)
|
||||
{
|
||||
clear_bit_unlock(nr, addr);
|
||||
arch_clear_bit_unlock(nr, addr);
|
||||
}
|
||||
|
||||
static inline bool xor_unlock_is_negative_byte(unsigned long mask,
|
||||
static inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long res;
|
||||
@@ -369,6 +369,9 @@ static inline bool xor_unlock_is_negative_byte(unsigned long mask,
|
||||
#undef __NOT
|
||||
#undef __AMO
|
||||
|
||||
#include <asm-generic/bitops/instrumented-atomic.h>
|
||||
#include <asm-generic/bitops/instrumented-lock.h>
|
||||
|
||||
#include <asm-generic/bitops/non-atomic.h>
|
||||
#include <asm-generic/bitops/le.h>
|
||||
#include <asm-generic/bitops/ext2-atomic.h>
|
||||
|
||||
@@ -46,7 +46,23 @@ do { \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end)
|
||||
extern u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1];
|
||||
extern char _end[];
|
||||
#define flush_cache_vmap flush_cache_vmap
|
||||
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (is_vmalloc_or_module_addr((void *)start)) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We don't care if concurrently a cpu resets this value since
|
||||
* the only place this can happen is in handle_exception() where
|
||||
* an sfence.vma is emitted.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(new_vmalloc); ++i)
|
||||
new_vmalloc[i] = -1ULL;
|
||||
}
|
||||
}
|
||||
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __ASM_EXEC_H
|
||||
#define __ASM_EXEC_H
|
||||
|
||||
extern unsigned long arch_align_stack(unsigned long sp);
|
||||
|
||||
#endif /* __ASM_EXEC_H */
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef _ASM_RISCV_FENCE_H
|
||||
#define _ASM_RISCV_FENCE_H
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
#define RISCV_ISA_EXT_ZCF 83
|
||||
#define RISCV_ISA_EXT_ZCMOP 84
|
||||
#define RISCV_ISA_EXT_ZAWRS 85
|
||||
#define RISCV_ISA_EXT_SVVPTC 86
|
||||
|
||||
#define RISCV_ISA_EXT_XLINUXENVCFG 127
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
|
||||
#define INVALID_CONTEXT UINT_MAX
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu);
|
||||
#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
|
||||
#endif
|
||||
|
||||
void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
|
||||
|
||||
struct fwnode_handle *riscv_get_intc_hwnode(void);
|
||||
|
||||
@@ -112,11 +112,13 @@ struct kernel_mapping {
|
||||
/* Offset between linear mapping virtual address and kernel load address */
|
||||
unsigned long va_pa_offset;
|
||||
/* Offset between kernel mapping virtual address and kernel load address */
|
||||
unsigned long va_kernel_pa_offset;
|
||||
unsigned long va_kernel_xip_pa_offset;
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
unsigned long va_kernel_xip_text_pa_offset;
|
||||
unsigned long va_kernel_xip_data_pa_offset;
|
||||
uintptr_t xiprom;
|
||||
uintptr_t xiprom_sz;
|
||||
#else
|
||||
unsigned long va_kernel_pa_offset;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -134,12 +136,18 @@ extern phys_addr_t phys_ram_base;
|
||||
#else
|
||||
void *linear_mapping_pa_to_va(unsigned long x);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define kernel_mapping_pa_to_va(y) ({ \
|
||||
unsigned long _y = (unsigned long)(y); \
|
||||
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \
|
||||
(void *)(_y + kernel_map.va_kernel_xip_pa_offset) : \
|
||||
(void *)(_y + kernel_map.va_kernel_pa_offset + XIP_OFFSET); \
|
||||
(_y < phys_ram_base) ? \
|
||||
(void *)(_y + kernel_map.va_kernel_xip_text_pa_offset) : \
|
||||
(void *)(_y + kernel_map.va_kernel_xip_data_pa_offset); \
|
||||
})
|
||||
#else
|
||||
#define kernel_mapping_pa_to_va(y) ((void *)((unsigned long)(y) + kernel_map.va_kernel_pa_offset))
|
||||
#endif
|
||||
|
||||
#define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x)
|
||||
|
||||
#ifndef CONFIG_DEBUG_VIRTUAL
|
||||
@@ -147,12 +155,17 @@ void *linear_mapping_pa_to_va(unsigned long x);
|
||||
#else
|
||||
phys_addr_t linear_mapping_va_to_pa(unsigned long x);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define kernel_mapping_va_to_pa(y) ({ \
|
||||
unsigned long _y = (unsigned long)(y); \
|
||||
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \
|
||||
(_y - kernel_map.va_kernel_xip_pa_offset) : \
|
||||
(_y - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \
|
||||
(_y < kernel_map.virt_addr + kernel_map.xiprom_sz) ? \
|
||||
(_y - kernel_map.va_kernel_xip_text_pa_offset) : \
|
||||
(_y - kernel_map.va_kernel_xip_data_pa_offset); \
|
||||
})
|
||||
#else
|
||||
#define kernel_mapping_va_to_pa(y) ((unsigned long)(y) - kernel_map.va_kernel_pa_offset)
|
||||
#endif
|
||||
|
||||
#define __va_to_pa_nodebug(x) ({ \
|
||||
unsigned long _x = x; \
|
||||
|
||||
@@ -107,13 +107,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define XIP_OFFSET SZ_32M
|
||||
#define XIP_OFFSET_MASK (SZ_32M - 1)
|
||||
#else
|
||||
#define XIP_OFFSET 0
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/page.h>
|
||||
@@ -142,11 +135,14 @@
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define XIP_FIXUP(addr) ({ \
|
||||
extern char _sdata[], _start[], _end[]; \
|
||||
uintptr_t __rom_start_data = CONFIG_XIP_PHYS_ADDR \
|
||||
+ (uintptr_t)&_sdata - (uintptr_t)&_start; \
|
||||
uintptr_t __rom_end_data = CONFIG_XIP_PHYS_ADDR \
|
||||
+ (uintptr_t)&_end - (uintptr_t)&_start; \
|
||||
uintptr_t __a = (uintptr_t)(addr); \
|
||||
(__a >= CONFIG_XIP_PHYS_ADDR && \
|
||||
__a < CONFIG_XIP_PHYS_ADDR + XIP_OFFSET * 2) ? \
|
||||
__a - CONFIG_XIP_PHYS_ADDR + CONFIG_PHYS_RAM_BASE - XIP_OFFSET :\
|
||||
__a; \
|
||||
(__a >= __rom_start_data && __a < __rom_end_data) ? \
|
||||
__a - __rom_start_data + CONFIG_PHYS_RAM_BASE : __a; \
|
||||
})
|
||||
#else
|
||||
#define XIP_FIXUP(addr) (addr)
|
||||
@@ -501,6 +497,9 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
|
||||
struct vm_area_struct *vma, unsigned long address,
|
||||
pte_t *ptep, unsigned int nr)
|
||||
{
|
||||
asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1)
|
||||
: : : : svvptc);
|
||||
|
||||
/*
|
||||
* The kernel assumes that TLBs don't cache invalid entries, but
|
||||
* in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
|
||||
@@ -510,6 +509,13 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
|
||||
*/
|
||||
while (nr--)
|
||||
local_flush_tlb_page(address + nr * PAGE_SIZE);
|
||||
|
||||
svvptc:;
|
||||
/*
|
||||
* Svvptc guarantees that the new valid pte will be visible within
|
||||
* a bounded timeframe, so when the uarch does not cache invalid
|
||||
* entries, we don't have to do anything.
|
||||
*/
|
||||
}
|
||||
#define update_mmu_cache(vma, addr, ptep) \
|
||||
update_mmu_cache_range(NULL, vma, addr, ptep, 1)
|
||||
|
||||
@@ -159,6 +159,7 @@ struct riscv_pmu_snapshot_data {
|
||||
|
||||
#define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0)
|
||||
#define RISCV_PMU_RAW_EVENT_IDX 0x20000
|
||||
#define RISCV_PLAT_FW_EVENT 0xFFFF
|
||||
|
||||
/** General pmu event codes specified in SBI PMU extension */
|
||||
enum sbi_pmu_hw_generic_events_t {
|
||||
|
||||
@@ -46,7 +46,7 @@ bool kernel_page_present(struct page *page);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_XIP_KERNEL)
|
||||
#ifdef CONFIG_64BIT
|
||||
#define SECTION_ALIGN (1 << 21)
|
||||
#else
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifdef CONFIG_64BIT
|
||||
#define MAX_PHYSMEM_BITS 56
|
||||
#else
|
||||
#define MAX_PHYSMEM_BITS 34
|
||||
#define MAX_PHYSMEM_BITS 32
|
||||
#endif /* CONFIG_64BIT */
|
||||
#define SECTION_SIZE_BITS 27
|
||||
#endif /* CONFIG_SPARSEMEM */
|
||||
|
||||
@@ -19,6 +19,7 @@ extern asmlinkage void *__memcpy(void *, const void *, size_t);
|
||||
extern asmlinkage void *memmove(void *, const void *, size_t);
|
||||
extern asmlinkage void *__memmove(void *, const void *, size_t);
|
||||
|
||||
#if !(defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS))
|
||||
#define __HAVE_ARCH_STRCMP
|
||||
extern asmlinkage int strcmp(const char *cs, const char *ct);
|
||||
|
||||
@@ -27,6 +28,7 @@ extern asmlinkage __kernel_size_t strlen(const char *);
|
||||
|
||||
#define __HAVE_ARCH_STRNCMP
|
||||
extern asmlinkage int strncmp(const char *cs, const char *ct, size_t count);
|
||||
#endif
|
||||
|
||||
/* For those files which don't want to check by kasan. */
|
||||
#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
|
||||
|
||||
@@ -61,6 +61,13 @@ struct thread_info {
|
||||
void *scs_base;
|
||||
void *scs_sp;
|
||||
#endif
|
||||
#ifdef CONFIG_64BIT
|
||||
/*
|
||||
* Used in handle_exception() to save a0, a1 and a2 before knowing if we
|
||||
* can access the kernel stack.
|
||||
*/
|
||||
unsigned long a0, a1, a2;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SHADOW_CALL_STACK
|
||||
@@ -112,8 +119,4 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
|
||||
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
||||
#define _TIF_RISCV_V_DEFER_RESTORE (1 << TIF_RISCV_V_DEFER_RESTORE)
|
||||
|
||||
#define _TIF_WORK_MASK \
|
||||
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_NOTIFY_SIGNAL | _TIF_UPROBE)
|
||||
|
||||
#endif /* _ASM_RISCV_THREAD_INFO_H */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef _ASM_RISCV_VMALLOC_H
|
||||
#define _ASM_RISCV_VMALLOC_H
|
||||
|
||||
|
||||
@@ -9,18 +9,36 @@
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
.macro XIP_FIXUP_OFFSET reg
|
||||
REG_L t0, _xip_fixup
|
||||
/* Fix-up address in Flash into address in RAM early during boot before
|
||||
* MMU is up. Because generated code "thinks" data is in Flash, but it
|
||||
* is actually in RAM (actually data is also in Flash, but Flash is
|
||||
* read-only, thus we need to use the data residing in RAM).
|
||||
*
|
||||
* The start of data in Flash is _sdata and the start of data in RAM is
|
||||
* CONFIG_PHYS_RAM_BASE. So this fix-up essentially does this:
|
||||
* reg += CONFIG_PHYS_RAM_BASE - _start
|
||||
*/
|
||||
li t0, CONFIG_PHYS_RAM_BASE
|
||||
add \reg, \reg, t0
|
||||
la t0, _sdata
|
||||
sub \reg, \reg, t0
|
||||
.endm
|
||||
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||
/* In linker script, at the transition from read-only section to
|
||||
* writable section, the VMA is increased while LMA remains the same.
|
||||
* (See in linker script how _sdata, __data_loc and LOAD_OFFSET is
|
||||
* changed)
|
||||
*
|
||||
* Consequently, early during boot before MMU is up, the generated code
|
||||
* reads the "writable" section at wrong addresses, because VMA is used
|
||||
* by compiler to generate code, but the data is located in Flash using
|
||||
* LMA.
|
||||
*/
|
||||
la t0, _sdata
|
||||
sub \reg, \reg, t0
|
||||
la t0, __data_loc
|
||||
REG_L t1, _xip_phys_offset
|
||||
sub \reg, \reg, t1
|
||||
add \reg, \reg, t0
|
||||
.endm
|
||||
|
||||
_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET
|
||||
_xip_phys_offset: .dword CONFIG_XIP_PHYS_ADDR + XIP_OFFSET
|
||||
#else
|
||||
.macro XIP_FIXUP_OFFSET reg
|
||||
.endm
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE };
|
||||
|
||||
int __init acpi_numa_get_nid(unsigned int cpu)
|
||||
static int __init acpi_numa_get_nid(unsigned int cpu)
|
||||
{
|
||||
return acpi_early_node_map[cpu];
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ void asm_offsets(void)
|
||||
OFFSET(TASK_THREAD_S9, task_struct, thread.s[9]);
|
||||
OFFSET(TASK_THREAD_S10, task_struct, thread.s[10]);
|
||||
OFFSET(TASK_THREAD_S11, task_struct, thread.s[11]);
|
||||
|
||||
OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
|
||||
OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags);
|
||||
OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
|
||||
OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
|
||||
@@ -43,6 +45,11 @@ void asm_offsets(void)
|
||||
#ifdef CONFIG_SHADOW_CALL_STACK
|
||||
OFFSET(TASK_TI_SCS_SP, task_struct, thread_info.scs_sp);
|
||||
#endif
|
||||
#ifdef CONFIG_64BIT
|
||||
OFFSET(TASK_TI_A0, task_struct, thread_info.a0);
|
||||
OFFSET(TASK_TI_A1, task_struct, thread_info.a1);
|
||||
OFFSET(TASK_TI_A2, task_struct, thread_info.a2);
|
||||
#endif
|
||||
|
||||
OFFSET(TASK_TI_CPU_NUM, task_struct, thread_info.cpu);
|
||||
OFFSET(TASK_THREAD_F0, task_struct, thread.fstate.f[0]);
|
||||
|
||||
@@ -71,6 +71,11 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
|
||||
this_leaf->type = type;
|
||||
}
|
||||
|
||||
int init_cache_level(unsigned int cpu)
|
||||
{
|
||||
return init_of_cache_level(cpu);
|
||||
}
|
||||
|
||||
int populate_cache_leaves(unsigned int cpu)
|
||||
{
|
||||
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
||||
|
||||
@@ -381,6 +381,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
|
||||
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
|
||||
__RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT),
|
||||
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
|
||||
__RISCV_ISA_EXT_DATA(svvptc, RISCV_ISA_EXT_SVVPTC),
|
||||
};
|
||||
|
||||
const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);
|
||||
|
||||
@@ -451,6 +451,12 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
|
||||
*(u32 *)loc = CLEAN_IMM(CJTYPE, *(u32 *)loc) |
|
||||
ENCODE_CJTYPE_IMM(val - addr);
|
||||
break;
|
||||
case R_RISCV_ADD16:
|
||||
*(u16 *)loc += val;
|
||||
break;
|
||||
case R_RISCV_SUB16:
|
||||
*(u16 *)loc -= val;
|
||||
break;
|
||||
case R_RISCV_ADD32:
|
||||
*(u32 *)loc += val;
|
||||
break;
|
||||
|
||||
@@ -19,6 +19,79 @@
|
||||
|
||||
.section .irqentry.text, "ax"
|
||||
|
||||
.macro new_vmalloc_check
|
||||
REG_S a0, TASK_TI_A0(tp)
|
||||
csrr a0, CSR_CAUSE
|
||||
/* Exclude IRQs */
|
||||
blt a0, zero, _new_vmalloc_restore_context_a0
|
||||
|
||||
REG_S a1, TASK_TI_A1(tp)
|
||||
/* Only check new_vmalloc if we are in page/protection fault */
|
||||
li a1, EXC_LOAD_PAGE_FAULT
|
||||
beq a0, a1, _new_vmalloc_kernel_address
|
||||
li a1, EXC_STORE_PAGE_FAULT
|
||||
beq a0, a1, _new_vmalloc_kernel_address
|
||||
li a1, EXC_INST_PAGE_FAULT
|
||||
bne a0, a1, _new_vmalloc_restore_context_a1
|
||||
|
||||
_new_vmalloc_kernel_address:
|
||||
/* Is it a kernel address? */
|
||||
csrr a0, CSR_TVAL
|
||||
bge a0, zero, _new_vmalloc_restore_context_a1
|
||||
|
||||
/* Check if a new vmalloc mapping appeared that could explain the trap */
|
||||
REG_S a2, TASK_TI_A2(tp)
|
||||
/*
|
||||
* Computes:
|
||||
* a0 = &new_vmalloc[BIT_WORD(cpu)]
|
||||
* a1 = BIT_MASK(cpu)
|
||||
*/
|
||||
REG_L a2, TASK_TI_CPU(tp)
|
||||
/*
|
||||
* Compute the new_vmalloc element position:
|
||||
* (cpu / 64) * 8 = (cpu >> 6) << 3
|
||||
*/
|
||||
srli a1, a2, 6
|
||||
slli a1, a1, 3
|
||||
la a0, new_vmalloc
|
||||
add a0, a0, a1
|
||||
/*
|
||||
* Compute the bit position in the new_vmalloc element:
|
||||
* bit_pos = cpu % 64 = cpu - (cpu / 64) * 64 = cpu - (cpu >> 6) << 6
|
||||
* = cpu - ((cpu >> 6) << 3) << 3
|
||||
*/
|
||||
slli a1, a1, 3
|
||||
sub a1, a2, a1
|
||||
/* Compute the "get mask": 1 << bit_pos */
|
||||
li a2, 1
|
||||
sll a1, a2, a1
|
||||
|
||||
/* Check the value of new_vmalloc for this cpu */
|
||||
REG_L a2, 0(a0)
|
||||
and a2, a2, a1
|
||||
beq a2, zero, _new_vmalloc_restore_context
|
||||
|
||||
/* Atomically reset the current cpu bit in new_vmalloc */
|
||||
amoxor.d a0, a1, (a0)
|
||||
|
||||
/* Only emit a sfence.vma if the uarch caches invalid entries */
|
||||
ALTERNATIVE("sfence.vma", "nop", 0, RISCV_ISA_EXT_SVVPTC, 1)
|
||||
|
||||
REG_L a0, TASK_TI_A0(tp)
|
||||
REG_L a1, TASK_TI_A1(tp)
|
||||
REG_L a2, TASK_TI_A2(tp)
|
||||
csrw CSR_SCRATCH, x0
|
||||
sret
|
||||
|
||||
_new_vmalloc_restore_context:
|
||||
REG_L a2, TASK_TI_A2(tp)
|
||||
_new_vmalloc_restore_context_a1:
|
||||
REG_L a1, TASK_TI_A1(tp)
|
||||
_new_vmalloc_restore_context_a0:
|
||||
REG_L a0, TASK_TI_A0(tp)
|
||||
.endm
|
||||
|
||||
|
||||
SYM_CODE_START(handle_exception)
|
||||
/*
|
||||
* If coming from userspace, preserve the user thread pointer and load
|
||||
@@ -30,6 +103,20 @@ SYM_CODE_START(handle_exception)
|
||||
|
||||
.Lrestore_kernel_tpsp:
|
||||
csrr tp, CSR_SCRATCH
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/*
|
||||
* The RISC-V kernel does not eagerly emit a sfence.vma after each
|
||||
* new vmalloc mapping, which may result in exceptions:
|
||||
* - if the uarch caches invalid entries, the new mapping would not be
|
||||
* observed by the page table walker and an invalidation is needed.
|
||||
* - if the uarch does not cache invalid entries, a reordered access
|
||||
* could "miss" the new mapping and traps: in that case, we only need
|
||||
* to retry the access, no sfence.vma is required.
|
||||
*/
|
||||
new_vmalloc_check
|
||||
#endif
|
||||
|
||||
REG_S sp, TASK_TI_KERNEL_SP(tp)
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
@@ -239,8 +326,8 @@ SYM_CODE_START(ret_from_fork)
|
||||
jalr s0
|
||||
1:
|
||||
move a0, sp /* pt_regs */
|
||||
la ra, ret_from_exception
|
||||
tail syscall_exit_to_user_mode
|
||||
call syscall_exit_to_user_mode
|
||||
j ret_from_exception
|
||||
SYM_CODE_END(ret_from_fork)
|
||||
|
||||
#ifdef CONFIG_IRQ_STACKS
|
||||
|
||||
@@ -787,8 +787,8 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
|
||||
int res;
|
||||
unsigned int num_relocations = sechdrs[relsec].sh_size / sizeof(*rel);
|
||||
struct hlist_head *relocation_hashtable;
|
||||
struct list_head used_buckets_list;
|
||||
unsigned int hashtable_bits;
|
||||
LIST_HEAD(used_buckets_list);
|
||||
|
||||
hashtable_bits = initialize_relocation_hashtable(num_relocations,
|
||||
&relocation_hashtable);
|
||||
@@ -796,8 +796,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
|
||||
if (!relocation_hashtable)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&used_buckets_list);
|
||||
|
||||
pr_debug("Applying relocate section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
|
||||
|
||||
@@ -6,37 +6,9 @@
|
||||
|
||||
#include <asm/stacktrace.h>
|
||||
|
||||
/*
|
||||
* Get the return address for a single stackframe and return a pointer to the
|
||||
* next frame tail.
|
||||
*/
|
||||
static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
|
||||
unsigned long fp, unsigned long reg_ra)
|
||||
static bool fill_callchain(void *entry, unsigned long pc)
|
||||
{
|
||||
struct stackframe buftail;
|
||||
unsigned long ra = 0;
|
||||
unsigned long __user *user_frame_tail =
|
||||
(unsigned long __user *)(fp - sizeof(struct stackframe));
|
||||
|
||||
/* Check accessibility of one struct frame_tail beyond */
|
||||
if (!access_ok(user_frame_tail, sizeof(buftail)))
|
||||
return 0;
|
||||
if (__copy_from_user_inatomic(&buftail, user_frame_tail,
|
||||
sizeof(buftail)))
|
||||
return 0;
|
||||
|
||||
if (reg_ra != 0)
|
||||
ra = reg_ra;
|
||||
else
|
||||
ra = buftail.ra;
|
||||
|
||||
fp = buftail.fp;
|
||||
if (ra != 0)
|
||||
perf_callchain_store(entry, ra);
|
||||
else
|
||||
return 0;
|
||||
|
||||
return fp;
|
||||
return perf_callchain_store(entry, pc) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -56,19 +28,7 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
|
||||
void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fp = 0;
|
||||
|
||||
fp = regs->s0;
|
||||
perf_callchain_store(entry, regs->epc);
|
||||
|
||||
fp = user_backtrace(entry, fp, regs->ra);
|
||||
while (fp && !(fp & 0x3) && entry->nr < entry->max_stack)
|
||||
fp = user_backtrace(entry, fp, 0);
|
||||
}
|
||||
|
||||
static bool fill_callchain(void *entry, unsigned long pc)
|
||||
{
|
||||
return perf_callchain_store(entry, pc) == 0;
|
||||
arch_stack_walk_user(fill_callchain, entry, regs);
|
||||
}
|
||||
|
||||
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
|
||||
|
||||
@@ -5,6 +5,7 @@ KBUILD_CFLAGS := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) -fpie \
|
||||
-Os -DDISABLE_BRANCH_PROFILING $(DISABLE_STACKLEAK_PLUGIN) \
|
||||
$(call cc-option,-mbranch-protection=none) \
|
||||
-I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \
|
||||
-include $(srctree)/include/linux/hidden.h \
|
||||
-D__DISABLE_EXPORTS -ffreestanding \
|
||||
-fno-asynchronous-unwind-tables -fno-unwind-tables \
|
||||
$(call cc-option,-fno-addrsig)
|
||||
@@ -16,6 +17,7 @@ KBUILD_CFLAGS += -mcmodel=medany
|
||||
|
||||
CFLAGS_cmdline_early.o += -D__NO_FORTIFY
|
||||
CFLAGS_lib-fdt_ro.o += -D__NO_FORTIFY
|
||||
CFLAGS_fdt_early.o += -D__NO_FORTIFY
|
||||
|
||||
$(obj)/%.pi.o: OBJCOPYFLAGS := --prefix-symbols=__pi_ \
|
||||
--remove-section=.note.gnu.property \
|
||||
@@ -32,5 +34,5 @@ $(obj)/string.o: $(srctree)/lib/string.c FORCE
|
||||
$(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE
|
||||
$(call if_changed_rule,cc_o_c)
|
||||
|
||||
obj-y := cmdline_early.pi.o fdt_early.pi.o string.pi.o ctype.pi.o lib-fdt.pi.o lib-fdt_ro.pi.o
|
||||
obj-y := cmdline_early.pi.o fdt_early.pi.o string.pi.o ctype.pi.o lib-fdt.pi.o lib-fdt_ro.pi.o archrandom_early.pi.o
|
||||
extra-y := $(patsubst %.pi.o,%.o,$(obj-y))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <asm/csr.h>
|
||||
#include <linux/processor.h>
|
||||
|
||||
#include "pi.h"
|
||||
|
||||
/*
|
||||
* To avoid rewriting code include asm/archrandom.h and create macros
|
||||
* for the functions that won't be included.
|
||||
*/
|
||||
#undef riscv_has_extension_unlikely
|
||||
#define riscv_has_extension_likely(...) false
|
||||
#undef pr_err_once
|
||||
#define pr_err_once(...)
|
||||
|
||||
#include <asm/archrandom.h>
|
||||
|
||||
u64 get_kaslr_seed_zkr(const uintptr_t dtb_pa)
|
||||
{
|
||||
unsigned long seed = 0;
|
||||
|
||||
if (!fdt_early_match_extension_isa((const void *)dtb_pa, "zkr"))
|
||||
return 0;
|
||||
|
||||
if (!csr_seed_long(&seed))
|
||||
return 0;
|
||||
|
||||
return seed;
|
||||
}
|
||||
@@ -6,15 +6,9 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
static char early_cmdline[COMMAND_LINE_SIZE];
|
||||
#include "pi.h"
|
||||
|
||||
/*
|
||||
* Declare the functions that are exported (but prefixed) here so that LLVM
|
||||
* does not complain it lacks the 'static' keyword (which, if added, makes
|
||||
* LLVM complain because the function is actually unused in this file).
|
||||
*/
|
||||
u64 set_satp_mode_from_cmdline(uintptr_t dtb_pa);
|
||||
bool set_nokaslr_from_cmdline(uintptr_t dtb_pa);
|
||||
static char early_cmdline[COMMAND_LINE_SIZE];
|
||||
|
||||
static char *get_early_cmdline(uintptr_t dtb_pa)
|
||||
{
|
||||
|
||||
@@ -2,13 +2,9 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
/*
|
||||
* Declare the functions that are exported (but prefixed) here so that LLVM
|
||||
* does not complain it lacks the 'static' keyword (which, if added, makes
|
||||
* LLVM complain because the function is actually unused in this file).
|
||||
*/
|
||||
u64 get_kaslr_seed(uintptr_t dtb_pa);
|
||||
#include "pi.h"
|
||||
|
||||
u64 get_kaslr_seed(uintptr_t dtb_pa)
|
||||
{
|
||||
@@ -28,3 +24,162 @@ u64 get_kaslr_seed(uintptr_t dtb_pa)
|
||||
*prop = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* fdt_device_is_available - check if a device is available for use
|
||||
*
|
||||
* @fdt: pointer to the device tree blob
|
||||
* @node: offset of the node whose property to find
|
||||
*
|
||||
* Returns true if the status property is absent or set to "okay" or "ok",
|
||||
* false otherwise
|
||||
*/
|
||||
static bool fdt_device_is_available(const void *fdt, int node)
|
||||
{
|
||||
const char *status;
|
||||
int statlen;
|
||||
|
||||
status = fdt_getprop(fdt, node, "status", &statlen);
|
||||
if (!status)
|
||||
return true;
|
||||
|
||||
if (statlen > 0) {
|
||||
if (!strcmp(status, "okay") || !strcmp(status, "ok"))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy of fdt_nodename_eq_ */
|
||||
static int fdt_node_name_eq(const void *fdt, int offset,
|
||||
const char *s)
|
||||
{
|
||||
int olen;
|
||||
int len = strlen(s);
|
||||
const char *p = fdt_get_name(fdt, offset, &olen);
|
||||
|
||||
if (!p || olen < len)
|
||||
/* short match */
|
||||
return 0;
|
||||
|
||||
if (memcmp(p, s, len) != 0)
|
||||
return 0;
|
||||
|
||||
if (p[len] == '\0')
|
||||
return 1;
|
||||
else if (!memchr(s, '@', len) && (p[len] == '@'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* isa_string_contains - check if isa string contains an extension
|
||||
*
|
||||
* @isa_str: isa string to search
|
||||
* @ext_name: the extension to search for
|
||||
*
|
||||
* Returns true if the extension is in the given isa string,
|
||||
* false otherwise
|
||||
*/
|
||||
static bool isa_string_contains(const char *isa_str, const char *ext_name)
|
||||
{
|
||||
size_t i, single_end, len = strlen(ext_name);
|
||||
char ext_end;
|
||||
|
||||
/* Error must contain rv32/64 */
|
||||
if (strlen(isa_str) < 4)
|
||||
return false;
|
||||
|
||||
if (len == 1) {
|
||||
single_end = strcspn(isa_str, "sSxXzZ");
|
||||
/* Search for single chars between rv32/64 and multi-letter extensions */
|
||||
for (i = 4; i < single_end; i++) {
|
||||
if (tolower(isa_str[i]) == ext_name[0])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Skip to start of multi-letter extensions */
|
||||
isa_str = strpbrk(isa_str, "sSxXzZ");
|
||||
while (isa_str) {
|
||||
if (strncasecmp(isa_str, ext_name, len) == 0) {
|
||||
ext_end = isa_str[len];
|
||||
/* Check if matches the whole extension. */
|
||||
if (ext_end == '\0' || ext_end == '_')
|
||||
return true;
|
||||
}
|
||||
/* Multi-letter extensions must be split from other multi-letter
|
||||
* extensions with an "_", the end of a multi-letter extension will
|
||||
* either be the null character or the "_" at the start of the next
|
||||
* multi-letter extension.
|
||||
*/
|
||||
isa_str = strchr(isa_str, '_');
|
||||
if (isa_str)
|
||||
isa_str++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* early_cpu_isa_ext_available - check if cpu node has an extension
|
||||
*
|
||||
* @fdt: pointer to the device tree blob
|
||||
* @node: offset of the cpu node
|
||||
* @ext_name: the extension to search for
|
||||
*
|
||||
* Returns true if the cpu node has the extension,
|
||||
* false otherwise
|
||||
*/
|
||||
static bool early_cpu_isa_ext_available(const void *fdt, int node, const char *ext_name)
|
||||
{
|
||||
const void *prop;
|
||||
int len;
|
||||
|
||||
prop = fdt_getprop(fdt, node, "riscv,isa-extensions", &len);
|
||||
if (prop && fdt_stringlist_contains(prop, len, ext_name))
|
||||
return true;
|
||||
|
||||
prop = fdt_getprop(fdt, node, "riscv,isa", &len);
|
||||
if (prop && isa_string_contains(prop, ext_name))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* fdt_early_match_extension_isa - check if all cpu nodes have an extension
|
||||
*
|
||||
* @fdt: pointer to the device tree blob
|
||||
* @ext_name: the extension to search for
|
||||
*
|
||||
* Returns true if the all available the cpu nodes have the extension,
|
||||
* false otherwise
|
||||
*/
|
||||
bool fdt_early_match_extension_isa(const void *fdt, const char *ext_name)
|
||||
{
|
||||
int node, parent;
|
||||
bool ret = false;
|
||||
|
||||
parent = fdt_path_offset(fdt, "/cpus");
|
||||
if (parent < 0)
|
||||
return false;
|
||||
|
||||
fdt_for_each_subnode(node, fdt, parent) {
|
||||
if (!fdt_node_name_eq(fdt, node, "cpu"))
|
||||
continue;
|
||||
|
||||
if (!fdt_device_is_available(fdt, node))
|
||||
continue;
|
||||
|
||||
if (!early_cpu_isa_ext_available(fdt, node, ext_name))
|
||||
return false;
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _RISCV_PI_H_
|
||||
#define _RISCV_PI_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* The following functions are exported (but prefixed). Declare them here so
|
||||
* that LLVM does not complain it lacks the 'static' keyword (which, if
|
||||
* added, makes LLVM complain because the function is unused).
|
||||
*/
|
||||
|
||||
u64 get_kaslr_seed(uintptr_t dtb_pa);
|
||||
u64 get_kaslr_seed_zkr(const uintptr_t dtb_pa);
|
||||
bool set_nokaslr_from_cmdline(uintptr_t dtb_pa);
|
||||
u64 set_satp_mode_from_cmdline(uintptr_t dtb_pa);
|
||||
|
||||
bool fdt_early_match_extension_isa(const void *fdt, const char *ext_name);
|
||||
|
||||
#endif /* _RISCV_PI_H_ */
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/tick.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/personality.h>
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -26,6 +27,7 @@
|
||||
#include <asm/cpuidle.h>
|
||||
#include <asm/vector.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/exec.h>
|
||||
|
||||
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK)
|
||||
#include <linux/stackprotector.h>
|
||||
@@ -99,6 +101,13 @@ void show_regs(struct pt_regs *regs)
|
||||
dump_backtrace(regs, NULL, KERN_DEFAULT);
|
||||
}
|
||||
|
||||
unsigned long arch_align_stack(unsigned long sp)
|
||||
{
|
||||
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
|
||||
sp -= get_random_u32_below(PAGE_SIZE);
|
||||
return sp & ~0xf;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static bool compat_mode_supported __read_mostly;
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
EXPORT_SYMBOL(memset);
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(memmove);
|
||||
EXPORT_SYMBOL(strcmp);
|
||||
EXPORT_SYMBOL(strlen);
|
||||
EXPORT_SYMBOL(strncmp);
|
||||
EXPORT_SYMBOL(__memset);
|
||||
EXPORT_SYMBOL(__memcpy);
|
||||
EXPORT_SYMBOL(__memmove);
|
||||
|
||||
+41
-2
@@ -13,6 +13,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/kgdb.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/smp.h>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/nmi.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/cacheflush.h>
|
||||
@@ -33,6 +35,8 @@ enum ipi_message_type {
|
||||
IPI_CPU_CRASH_STOP,
|
||||
IPI_IRQ_WORK,
|
||||
IPI_TIMER,
|
||||
IPI_CPU_BACKTRACE,
|
||||
IPI_KGDB_ROUNDUP,
|
||||
IPI_MAX
|
||||
};
|
||||
|
||||
@@ -113,6 +117,7 @@ void arch_irq_work_raise(void)
|
||||
|
||||
static irqreturn_t handle_IPI(int irq, void *data)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int ipi = irq - ipi_virq_base;
|
||||
|
||||
switch (ipi) {
|
||||
@@ -126,7 +131,7 @@ static irqreturn_t handle_IPI(int irq, void *data)
|
||||
ipi_stop();
|
||||
break;
|
||||
case IPI_CPU_CRASH_STOP:
|
||||
ipi_cpu_crash_stop(smp_processor_id(), get_irq_regs());
|
||||
ipi_cpu_crash_stop(cpu, get_irq_regs());
|
||||
break;
|
||||
case IPI_IRQ_WORK:
|
||||
irq_work_run();
|
||||
@@ -136,8 +141,14 @@ static irqreturn_t handle_IPI(int irq, void *data)
|
||||
tick_receive_broadcast();
|
||||
break;
|
||||
#endif
|
||||
case IPI_CPU_BACKTRACE:
|
||||
nmi_cpu_backtrace(get_irq_regs());
|
||||
break;
|
||||
case IPI_KGDB_ROUNDUP:
|
||||
kgdb_nmicallback(cpu, get_irq_regs());
|
||||
break;
|
||||
default:
|
||||
pr_warn("CPU%d: unhandled IPI%d\n", smp_processor_id(), ipi);
|
||||
pr_warn("CPU%d: unhandled IPI%d\n", cpu, ipi);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -203,6 +214,8 @@ static const char * const ipi_names[] = {
|
||||
[IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts",
|
||||
[IPI_IRQ_WORK] = "IRQ work interrupts",
|
||||
[IPI_TIMER] = "Timer broadcast interrupts",
|
||||
[IPI_CPU_BACKTRACE] = "CPU backtrace interrupts",
|
||||
[IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts",
|
||||
};
|
||||
|
||||
void show_ipi_stats(struct seq_file *p, int prec)
|
||||
@@ -323,3 +336,29 @@ void arch_smp_send_reschedule(int cpu)
|
||||
send_ipi_single(cpu, IPI_RESCHEDULE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_smp_send_reschedule);
|
||||
|
||||
static void riscv_backtrace_ipi(cpumask_t *mask)
|
||||
{
|
||||
send_ipi_mask(mask, IPI_CPU_BACKTRACE);
|
||||
}
|
||||
|
||||
void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu)
|
||||
{
|
||||
nmi_trigger_cpumask_backtrace(mask, exclude_cpu, riscv_backtrace_ipi);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
void kgdb_roundup_cpus(void)
|
||||
{
|
||||
int this_cpu = raw_smp_processor_id();
|
||||
int cpu;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
/* No need to roundup ourselves */
|
||||
if (cpu == this_cpu)
|
||||
continue;
|
||||
|
||||
send_ipi_single(cpu, IPI_KGDB_ROUNDUP);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -162,3 +162,46 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry, void
|
||||
{
|
||||
walk_stackframe(task, regs, consume_entry, cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the return address for a single stackframe and return a pointer to the
|
||||
* next frame tail.
|
||||
*/
|
||||
static unsigned long unwind_user_frame(stack_trace_consume_fn consume_entry,
|
||||
void *cookie, unsigned long fp,
|
||||
unsigned long reg_ra)
|
||||
{
|
||||
struct stackframe buftail;
|
||||
unsigned long ra = 0;
|
||||
unsigned long __user *user_frame_tail =
|
||||
(unsigned long __user *)(fp - sizeof(struct stackframe));
|
||||
|
||||
/* Check accessibility of one struct frame_tail beyond */
|
||||
if (!access_ok(user_frame_tail, sizeof(buftail)))
|
||||
return 0;
|
||||
if (__copy_from_user_inatomic(&buftail, user_frame_tail,
|
||||
sizeof(buftail)))
|
||||
return 0;
|
||||
|
||||
ra = reg_ra ? : buftail.ra;
|
||||
|
||||
fp = buftail.fp;
|
||||
if (!ra || !consume_entry(cookie, ra))
|
||||
return 0;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fp = 0;
|
||||
|
||||
fp = regs->s0;
|
||||
if (!consume_entry(cookie, regs->epc))
|
||||
return;
|
||||
|
||||
fp = unwind_user_frame(consume_entry, cookie, fp, regs->ra);
|
||||
while (fp && !(fp & 0x7))
|
||||
fp = unwind_user_frame(consume_entry, cookie, fp, 0);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ $(obj)/vdso.o: $(obj)/vdso.so
|
||||
# link rule for the .so file, .lds has to be first
|
||||
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
|
||||
$(call if_changed,vdsold)
|
||||
LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \
|
||||
LDFLAGS_vdso.so.dbg = -shared -soname=linux-vdso.so.1 \
|
||||
--build-id=sha1 --hash-style=both --eh-frame-hdr
|
||||
|
||||
# strip rule for the .so file
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
/* All Andes vendor extensions supported in Linux */
|
||||
const struct riscv_isa_ext_data riscv_isa_vendor_ext_andes[] = {
|
||||
static const struct riscv_isa_ext_data riscv_isa_vendor_ext_andes[] = {
|
||||
__RISCV_ISA_EXT_DATA(xandespmu, RISCV_ISA_VENDOR_EXT_XANDESPMU),
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@ void arch_crash_save_vmcoreinfo(void)
|
||||
#endif
|
||||
#endif
|
||||
vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR);
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
/* TODO: Communicate with crash-utility developers on the information to
|
||||
* export. The XIP case is more complicated, because the virtual-physical
|
||||
* address offset depends on whether the address is in ROM or in RAM.
|
||||
*/
|
||||
#else
|
||||
vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n",
|
||||
kernel_map.va_kernel_pa_offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <asm/page.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
@@ -65,10 +66,10 @@ SECTIONS
|
||||
* From this point, stuff is considered writable and will be copied to RAM
|
||||
*/
|
||||
__data_loc = ALIGN(PAGE_SIZE); /* location in file */
|
||||
. = KERNEL_LINK_ADDR + XIP_OFFSET; /* location in memory */
|
||||
. = ALIGN(SECTION_ALIGN); /* location in memory */
|
||||
|
||||
#undef LOAD_OFFSET
|
||||
#define LOAD_OFFSET (KERNEL_LINK_ADDR + XIP_OFFSET - (__data_loc & XIP_OFFSET_MASK))
|
||||
#define LOAD_OFFSET (KERNEL_LINK_ADDR + _sdata - __data_loc)
|
||||
|
||||
_sdata = .; /* Start of data section */
|
||||
_data = .;
|
||||
|
||||
@@ -3,9 +3,11 @@ lib-y += delay.o
|
||||
lib-y += memcpy.o
|
||||
lib-y += memset.o
|
||||
lib-y += memmove.o
|
||||
ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),)
|
||||
lib-y += strcmp.o
|
||||
lib-y += strlen.o
|
||||
lib-y += strncmp.o
|
||||
endif
|
||||
lib-y += csum.o
|
||||
ifeq ($(CONFIG_MMU), y)
|
||||
lib-$(CONFIG_RISCV_ISA_V) += uaccess_vector.o
|
||||
|
||||
@@ -111,3 +111,5 @@ SYM_FUNC_START(__memset)
|
||||
ret
|
||||
SYM_FUNC_END(__memset)
|
||||
SYM_FUNC_ALIAS_WEAK(memset, __memset)
|
||||
SYM_FUNC_ALIAS(__pi_memset, __memset)
|
||||
SYM_FUNC_ALIAS(__pi___memset, __memset)
|
||||
|
||||
@@ -120,3 +120,5 @@ strcmp_zbb:
|
||||
.option pop
|
||||
#endif
|
||||
SYM_FUNC_END(strcmp)
|
||||
SYM_FUNC_ALIAS(__pi_strcmp, strcmp)
|
||||
EXPORT_SYMBOL(strcmp)
|
||||
|
||||
@@ -131,3 +131,4 @@ strlen_zbb:
|
||||
#endif
|
||||
SYM_FUNC_END(strlen)
|
||||
SYM_FUNC_ALIAS(__pi_strlen, strlen)
|
||||
EXPORT_SYMBOL(strlen)
|
||||
|
||||
@@ -136,3 +136,5 @@ strncmp_zbb:
|
||||
.option pop
|
||||
#endif
|
||||
SYM_FUNC_END(strncmp)
|
||||
SYM_FUNC_ALIAS(__pi_strncmp, strncmp)
|
||||
EXPORT_SYMBOL(strncmp)
|
||||
|
||||
+15
-13
@@ -37,6 +37,8 @@
|
||||
|
||||
#include "../kernel/head.h"
|
||||
|
||||
u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1];
|
||||
|
||||
struct kernel_mapping kernel_map __ro_after_init;
|
||||
EXPORT_SYMBOL(kernel_map);
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
@@ -917,7 +919,7 @@ static void __init relocate_kernel(void)
|
||||
static void __init create_kernel_page_table(pgd_t *pgdir,
|
||||
__always_unused bool early)
|
||||
{
|
||||
uintptr_t va, end_va;
|
||||
uintptr_t va, start_va, end_va;
|
||||
|
||||
/* Map the flash resident part */
|
||||
end_va = kernel_map.virt_addr + kernel_map.xiprom_sz;
|
||||
@@ -927,10 +929,11 @@ static void __init create_kernel_page_table(pgd_t *pgdir,
|
||||
PMD_SIZE, PAGE_KERNEL_EXEC);
|
||||
|
||||
/* Map the data in RAM */
|
||||
start_va = kernel_map.virt_addr + (uintptr_t)&_sdata - (uintptr_t)&_start;
|
||||
end_va = kernel_map.virt_addr + kernel_map.size;
|
||||
for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE)
|
||||
for (va = start_va; va < end_va; va += PMD_SIZE)
|
||||
create_pgd_mapping(pgdir, va,
|
||||
kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)),
|
||||
kernel_map.phys_addr + (va - start_va),
|
||||
PMD_SIZE, PAGE_KERNEL);
|
||||
}
|
||||
#else
|
||||
@@ -1048,6 +1051,7 @@ static void __init pt_ops_set_late(void)
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
extern bool __init __pi_set_nokaslr_from_cmdline(uintptr_t dtb_pa);
|
||||
extern u64 __init __pi_get_kaslr_seed(uintptr_t dtb_pa);
|
||||
extern u64 __init __pi_get_kaslr_seed_zkr(const uintptr_t dtb_pa);
|
||||
|
||||
static int __init print_nokaslr(char *p)
|
||||
{
|
||||
@@ -1068,10 +1072,12 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
if (!__pi_set_nokaslr_from_cmdline(dtb_pa)) {
|
||||
u64 kaslr_seed = __pi_get_kaslr_seed(dtb_pa);
|
||||
u64 kaslr_seed = __pi_get_kaslr_seed_zkr(dtb_pa);
|
||||
u32 kernel_size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
|
||||
u32 nr_pos;
|
||||
|
||||
if (kaslr_seed == 0)
|
||||
kaslr_seed = __pi_get_kaslr_seed(dtb_pa);
|
||||
/*
|
||||
* Compute the number of positions available: we are limited
|
||||
* by the early page table that only has one PUD and we must
|
||||
@@ -1098,11 +1104,14 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
|
||||
kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
|
||||
|
||||
kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom;
|
||||
kernel_map.va_kernel_xip_text_pa_offset = kernel_map.virt_addr - kernel_map.xiprom;
|
||||
kernel_map.va_kernel_xip_data_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr
|
||||
+ (uintptr_t)&_sdata - (uintptr_t)&_start;
|
||||
#else
|
||||
kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL);
|
||||
kernel_map.phys_addr = (uintptr_t)(&_start);
|
||||
kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr;
|
||||
kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL)
|
||||
@@ -1124,15 +1133,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
*/
|
||||
kernel_map.va_pa_offset = IS_ENABLED(CONFIG_64BIT) ?
|
||||
0UL : PAGE_OFFSET - kernel_map.phys_addr;
|
||||
kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr;
|
||||
|
||||
/*
|
||||
* The default maximal physical memory size is KERN_VIRT_SIZE for 32-bit
|
||||
* kernel, whereas for 64-bit kernel, the end of the virtual address
|
||||
* space is occupied by the modules/BPF/kernel mappings which reduces
|
||||
* the available size of the linear mapping.
|
||||
*/
|
||||
memory_limit = KERN_VIRT_SIZE - (IS_ENABLED(CONFIG_64BIT) ? SZ_4G : 0);
|
||||
memory_limit = KERN_VIRT_SIZE;
|
||||
|
||||
/* Sanity check alignment and size */
|
||||
BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0);
|
||||
|
||||
@@ -9,6 +9,9 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long address, pte_t *ptep,
|
||||
pte_t entry, int dirty)
|
||||
{
|
||||
asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1)
|
||||
: : : : svvptc);
|
||||
|
||||
if (!pte_same(ptep_get(ptep), entry))
|
||||
__set_pte_at(vma->vm_mm, ptep, entry);
|
||||
/*
|
||||
@@ -16,6 +19,16 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
* the case that the PTE changed and the spurious fault case.
|
||||
*/
|
||||
return true;
|
||||
|
||||
svvptc:
|
||||
if (!pte_same(ptep_get(ptep), entry)) {
|
||||
__set_pte_at(vma->vm_mm, ptep, entry);
|
||||
/* Here only not svadu is impacted */
|
||||
flush_tlb_page(vma, address);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ptep_test_and_clear_young(struct vm_area_struct *vma,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o
|
||||
ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),)
|
||||
purgatory-y += strcmp.o strlen.o strncmp.o
|
||||
endif
|
||||
|
||||
targets += $(purgatory-y)
|
||||
PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
|
||||
|
||||
@@ -802,7 +802,10 @@ out_err:
|
||||
module_init(paes_s390_init);
|
||||
module_exit(paes_s390_fini);
|
||||
|
||||
MODULE_ALIAS_CRYPTO("paes");
|
||||
MODULE_ALIAS_CRYPTO("ecb(paes)");
|
||||
MODULE_ALIAS_CRYPTO("cbc(paes)");
|
||||
MODULE_ALIAS_CRYPTO("ctr(paes)");
|
||||
MODULE_ALIAS_CRYPTO("xts(paes)");
|
||||
|
||||
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm with protected keys");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -708,6 +708,7 @@ static struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req,
|
||||
GFP_KERNEL : GFP_ATOMIC;
|
||||
struct ahash_edesc *edesc;
|
||||
|
||||
sg_num = pad_sg_nents(sg_num);
|
||||
edesc = kzalloc(struct_size(edesc, sec4_sg, sg_num), flags);
|
||||
if (!edesc)
|
||||
return NULL;
|
||||
|
||||
@@ -1640,8 +1640,10 @@ int ib_cache_setup_one(struct ib_device *device)
|
||||
|
||||
rdma_for_each_port (device, p) {
|
||||
err = ib_cache_update(device, p, true, true, true);
|
||||
if (err)
|
||||
if (err) {
|
||||
gid_table_cleanup_one(device);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -325,9 +325,6 @@ void ib_qp_usecnt_inc(struct ib_qp *qp);
|
||||
void ib_qp_usecnt_dec(struct ib_qp *qp);
|
||||
|
||||
struct rdma_dev_addr;
|
||||
int rdma_resolve_ip_route(struct sockaddr *src_addr,
|
||||
const struct sockaddr *dst_addr,
|
||||
struct rdma_dev_addr *addr);
|
||||
|
||||
int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
|
||||
const union ib_gid *dgid,
|
||||
|
||||
@@ -1351,6 +1351,29 @@ static void prevent_dealloc_device(struct ib_device *ib_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void ib_device_notify_register(struct ib_device *device)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
u32 port;
|
||||
int ret;
|
||||
|
||||
ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
rdma_for_each_port(device, port) {
|
||||
netdev = ib_device_get_netdev(device, port);
|
||||
if (!netdev)
|
||||
continue;
|
||||
|
||||
ret = rdma_nl_notify_event(device, port,
|
||||
RDMA_NETDEV_ATTACH_EVENT);
|
||||
dev_put(netdev);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_register_device - Register an IB device with IB core
|
||||
* @device: Device to register
|
||||
@@ -1449,6 +1472,8 @@ int ib_register_device(struct ib_device *device, const char *name,
|
||||
dev_set_uevent_suppress(&device->dev, false);
|
||||
/* Mark for userspace that device is ready */
|
||||
kobject_uevent(&device->dev.kobj, KOBJ_ADD);
|
||||
|
||||
ib_device_notify_register(device);
|
||||
ib_device_put(device);
|
||||
|
||||
return 0;
|
||||
@@ -1491,6 +1516,7 @@ static void __ib_unregister_device(struct ib_device *ib_dev)
|
||||
goto out;
|
||||
|
||||
disable_device(ib_dev);
|
||||
rdma_nl_notify_event(ib_dev, 0, RDMA_UNREGISTER_EVENT);
|
||||
|
||||
/* Expedite removing unregistered pointers from the hash table */
|
||||
free_netdevs(ib_dev);
|
||||
@@ -2159,6 +2185,7 @@ static void add_ndev_hash(struct ib_port_data *pdata)
|
||||
int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
|
||||
u32 port)
|
||||
{
|
||||
enum rdma_nl_notify_event_type etype;
|
||||
struct net_device *old_ndev;
|
||||
struct ib_port_data *pdata;
|
||||
unsigned long flags;
|
||||
@@ -2190,6 +2217,14 @@ int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
|
||||
spin_unlock_irqrestore(&pdata->netdev_lock, flags);
|
||||
|
||||
add_ndev_hash(pdata);
|
||||
|
||||
/* Make sure that the device is registered before we send events */
|
||||
if (xa_load(&devices, ib_dev->index) != ib_dev)
|
||||
return 0;
|
||||
|
||||
etype = ndev ? RDMA_NETDEV_ATTACH_EVENT : RDMA_NETDEV_DETACH_EVENT;
|
||||
rdma_nl_notify_event(ib_dev, port, etype);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_device_set_netdev);
|
||||
@@ -2236,6 +2271,9 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
|
||||
if (!rdma_is_port_valid(ib_dev, port))
|
||||
return NULL;
|
||||
|
||||
if (!ib_dev->port_data)
|
||||
return NULL;
|
||||
|
||||
pdata = &ib_dev->port_data[port];
|
||||
|
||||
/*
|
||||
@@ -2252,17 +2290,9 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
|
||||
spin_unlock(&pdata->netdev_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are starting to unregister expedite things by preventing
|
||||
* propagation of an unregistering netdev.
|
||||
*/
|
||||
if (res && res->reg_state != NETREG_REGISTERED) {
|
||||
dev_put(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_device_get_netdev);
|
||||
|
||||
/**
|
||||
* ib_device_get_by_netdev - Find an IB device associated with a netdev
|
||||
|
||||
@@ -1182,7 +1182,7 @@ static int __init iw_cm_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", 0);
|
||||
iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", WQ_MEM_RECLAIM);
|
||||
if (!iwcm_wq)
|
||||
goto err_alloc;
|
||||
|
||||
|
||||
@@ -2616,14 +2616,16 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
|
||||
static void timeout_sends(struct work_struct *work)
|
||||
{
|
||||
struct ib_mad_send_wr_private *mad_send_wr, *n;
|
||||
struct ib_mad_agent_private *mad_agent_priv;
|
||||
struct ib_mad_send_wr_private *mad_send_wr;
|
||||
struct ib_mad_send_wc mad_send_wc;
|
||||
struct list_head local_list;
|
||||
unsigned long flags, delay;
|
||||
|
||||
mad_agent_priv = container_of(work, struct ib_mad_agent_private,
|
||||
timed_work.work);
|
||||
mad_send_wc.vendor_err = 0;
|
||||
INIT_LIST_HEAD(&local_list);
|
||||
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
while (!list_empty(&mad_agent_priv->wait_list)) {
|
||||
@@ -2641,13 +2643,16 @@ static void timeout_sends(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
list_del(&mad_send_wr->agent_list);
|
||||
list_del_init(&mad_send_wr->agent_list);
|
||||
if (mad_send_wr->status == IB_WC_SUCCESS &&
|
||||
!retry_send(mad_send_wr))
|
||||
continue;
|
||||
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
list_add_tail(&mad_send_wr->agent_list, &local_list);
|
||||
}
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
|
||||
list_for_each_entry_safe(mad_send_wr, n, &local_list, agent_list) {
|
||||
if (mad_send_wr->status == IB_WC_SUCCESS)
|
||||
mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR;
|
||||
else
|
||||
@@ -2655,11 +2660,8 @@ static void timeout_sends(struct work_struct *work)
|
||||
mad_send_wc.send_buf = &mad_send_wr->send_buf;
|
||||
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
|
||||
&mad_send_wc);
|
||||
|
||||
deref_mad_agent(mad_agent_priv);
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2937,7 +2939,6 @@ static int ib_mad_port_open(struct ib_device *device,
|
||||
int ret, cq_size;
|
||||
struct ib_mad_port_private *port_priv;
|
||||
unsigned long flags;
|
||||
char name[sizeof "ib_mad123"];
|
||||
int has_smi;
|
||||
|
||||
if (WARN_ON(rdma_max_mad_size(device, port_num) < IB_MGMT_MAD_SIZE))
|
||||
@@ -2990,8 +2991,8 @@ static int ib_mad_port_open(struct ib_device *device,
|
||||
goto error7;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "ib_mad%u", port_num);
|
||||
port_priv->wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
|
||||
port_priv->wq = alloc_ordered_workqueue("ib_mad%u", WQ_MEM_RECLAIM,
|
||||
port_num);
|
||||
if (!port_priv->wq) {
|
||||
ret = -ENOMEM;
|
||||
goto error8;
|
||||
|
||||
@@ -311,6 +311,7 @@ int rdma_nl_net_init(struct rdma_dev_net *rnet)
|
||||
struct net *net = read_pnet(&rnet->net);
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.input = rdma_nl_rcv,
|
||||
.flags = NL_CFG_F_NONROOT_RECV,
|
||||
};
|
||||
struct sock *nls;
|
||||
|
||||
|
||||
+159
-28
@@ -170,6 +170,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
|
||||
[RDMA_NLDEV_ATTR_DEV_TYPE] = { .type = NLA_U8 },
|
||||
[RDMA_NLDEV_ATTR_PARENT_NAME] = { .type = NLA_NUL_STRING },
|
||||
[RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE] = { .type = NLA_U8 },
|
||||
[RDMA_NLDEV_ATTR_EVENT_TYPE] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
|
||||
@@ -1074,8 +1075,8 @@ static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
u32 index;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1123,8 +1124,8 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
u32 index;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1215,8 +1216,8 @@ static int nldev_port_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
u32 port;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (err ||
|
||||
!tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
|
||||
!tb[RDMA_NLDEV_ATTR_PORT_INDEX])
|
||||
@@ -1275,8 +1276,8 @@ static int nldev_port_get_dumpit(struct sk_buff *skb,
|
||||
int err;
|
||||
unsigned int p;
|
||||
|
||||
err = nlmsg_parse_deprecated(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NULL);
|
||||
err = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, NULL);
|
||||
if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1331,8 +1332,8 @@ static int nldev_res_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
u32 index;
|
||||
int ret;
|
||||
|
||||
ret = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1481,8 +1482,8 @@ static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct sk_buff *msg;
|
||||
int ret;
|
||||
|
||||
ret = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !fe->id || !tb[fe->id])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1569,8 +1570,8 @@ static int res_get_common_dumpit(struct sk_buff *skb,
|
||||
u32 index, port = 0;
|
||||
bool filled = false;
|
||||
|
||||
err = nlmsg_parse_deprecated(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NULL);
|
||||
err = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, NULL);
|
||||
/*
|
||||
* Right now, we are expecting the device index to get res information,
|
||||
* but it is possible to extend this code to return all devices in
|
||||
@@ -1762,8 +1763,8 @@ static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
char type[IFNAMSIZ];
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
if (err || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_LINK_TYPE] || !tb[RDMA_NLDEV_ATTR_NDEV_NAME])
|
||||
return -EINVAL;
|
||||
@@ -1806,8 +1807,8 @@ static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
u32 index;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse_deprecated(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1836,8 +1837,8 @@ static int nldev_get_chardev(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
u32 index;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,
|
||||
extack);
|
||||
err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,
|
||||
NL_VALIDATE_LIBERAL, extack);
|
||||
if (err || !tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1920,8 +1921,8 @@ static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct sk_buff *msg;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1951,6 +1952,12 @@ static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_MONITOR_MODE, 1);
|
||||
if (err) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* Copy-on-fork is supported.
|
||||
* See commits:
|
||||
@@ -2420,8 +2427,8 @@ static int nldev_stat_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
|
||||
int ret;
|
||||
|
||||
ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -2450,8 +2457,8 @@ static int nldev_stat_get_dumpit(struct sk_buff *skb,
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
|
||||
int ret;
|
||||
|
||||
ret = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NULL);
|
||||
ret = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, NULL);
|
||||
if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -2482,8 +2489,8 @@ static int nldev_stat_get_counter_status_doit(struct sk_buff *skb,
|
||||
u32 devid, port;
|
||||
int ret, i;
|
||||
|
||||
ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, extack);
|
||||
ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
|
||||
nldev_policy, NL_VALIDATE_LIBERAL, extack);
|
||||
if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
|
||||
!tb[RDMA_NLDEV_ATTR_PORT_INDEX])
|
||||
return -EINVAL;
|
||||
@@ -2722,6 +2729,130 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int fill_mon_netdev_association(struct sk_buff *msg,
|
||||
struct ib_device *device, u32 port,
|
||||
const struct net *net)
|
||||
{
|
||||
struct net_device *netdev = ib_device_get_netdev(device, port);
|
||||
int ret = 0;
|
||||
|
||||
if (netdev && !net_eq(dev_net(netdev), net))
|
||||
goto out;
|
||||
|
||||
ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_DEV_INDEX, device->index);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_NAME,
|
||||
dev_name(&device->dev));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (netdev) {
|
||||
ret = nla_put_u32(msg,
|
||||
RDMA_NLDEV_ATTR_NDEV_INDEX, netdev->ifindex);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = nla_put_string(msg,
|
||||
RDMA_NLDEV_ATTR_NDEV_NAME, netdev->name);
|
||||
}
|
||||
|
||||
out:
|
||||
dev_put(netdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rdma_nl_notify_err_msg(struct ib_device *device, u32 port_num,
|
||||
enum rdma_nl_notify_event_type type)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
|
||||
switch (type) {
|
||||
case RDMA_REGISTER_EVENT:
|
||||
dev_warn_ratelimited(&device->dev,
|
||||
"Failed to send RDMA monitor register device event\n");
|
||||
break;
|
||||
case RDMA_UNREGISTER_EVENT:
|
||||
dev_warn_ratelimited(&device->dev,
|
||||
"Failed to send RDMA monitor unregister device event\n");
|
||||
break;
|
||||
case RDMA_NETDEV_ATTACH_EVENT:
|
||||
netdev = ib_device_get_netdev(device, port_num);
|
||||
dev_warn_ratelimited(&device->dev,
|
||||
"Failed to send RDMA monitor netdev attach event: port %d netdev %d\n",
|
||||
port_num, netdev->ifindex);
|
||||
dev_put(netdev);
|
||||
break;
|
||||
case RDMA_NETDEV_DETACH_EVENT:
|
||||
dev_warn_ratelimited(&device->dev,
|
||||
"Failed to send RDMA monitor netdev detach event: port %d\n",
|
||||
port_num);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int rdma_nl_notify_event(struct ib_device *device, u32 port_num,
|
||||
enum rdma_nl_notify_event_type type)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct net *net;
|
||||
int ret = 0;
|
||||
void *nlh;
|
||||
|
||||
net = read_pnet(&device->coredev.rdma_net);
|
||||
if (!net)
|
||||
return -EINVAL;
|
||||
|
||||
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
nlh = nlmsg_put(skb, 0, 0,
|
||||
RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_MONITOR),
|
||||
0, 0);
|
||||
|
||||
switch (type) {
|
||||
case RDMA_REGISTER_EVENT:
|
||||
case RDMA_UNREGISTER_EVENT:
|
||||
ret = fill_nldev_handle(skb, device);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
break;
|
||||
case RDMA_NETDEV_ATTACH_EVENT:
|
||||
case RDMA_NETDEV_DETACH_EVENT:
|
||||
ret = fill_mon_netdev_association(skb, device,
|
||||
port_num, net);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = nla_put_u8(skb, RDMA_NLDEV_ATTR_EVENT_TYPE, type);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
ret = rdma_nl_multicast(net, skb, RDMA_NL_GROUP_NOTIFY, GFP_KERNEL);
|
||||
if (ret && ret != -ESRCH) {
|
||||
skb = NULL; /* skb is freed in the netlink send-op handling */
|
||||
goto err_free;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
rdma_nl_notify_err_msg(device, port_num, type);
|
||||
nlmsg_free(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __init nldev_init(void)
|
||||
{
|
||||
rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table);
|
||||
|
||||
@@ -23,6 +23,9 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
|
||||
|
||||
dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv);
|
||||
|
||||
if (umem_dmabuf->revoked)
|
||||
return -EINVAL;
|
||||
|
||||
if (umem_dmabuf->sgt)
|
||||
goto wait_fence;
|
||||
|
||||
@@ -110,10 +113,12 @@ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf)
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_dmabuf_unmap_pages);
|
||||
|
||||
struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device,
|
||||
unsigned long offset, size_t size,
|
||||
int fd, int access,
|
||||
const struct dma_buf_attach_ops *ops)
|
||||
static struct ib_umem_dmabuf *
|
||||
ib_umem_dmabuf_get_with_dma_device(struct ib_device *device,
|
||||
struct device *dma_device,
|
||||
unsigned long offset, size_t size,
|
||||
int fd, int access,
|
||||
const struct dma_buf_attach_ops *ops)
|
||||
{
|
||||
struct dma_buf *dmabuf;
|
||||
struct ib_umem_dmabuf *umem_dmabuf;
|
||||
@@ -152,7 +157,7 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device,
|
||||
|
||||
umem_dmabuf->attach = dma_buf_dynamic_attach(
|
||||
dmabuf,
|
||||
device->dma_device,
|
||||
dma_device,
|
||||
ops,
|
||||
umem_dmabuf);
|
||||
if (IS_ERR(umem_dmabuf->attach)) {
|
||||
@@ -168,6 +173,15 @@ out_release_dmabuf:
|
||||
dma_buf_put(dmabuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device,
|
||||
unsigned long offset, size_t size,
|
||||
int fd, int access,
|
||||
const struct dma_buf_attach_ops *ops)
|
||||
{
|
||||
return ib_umem_dmabuf_get_with_dma_device(device, device->dma_device,
|
||||
offset, size, fd, access, ops);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_dmabuf_get);
|
||||
|
||||
static void
|
||||
@@ -184,16 +198,18 @@ static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_ops = {
|
||||
.move_notify = ib_umem_dmabuf_unsupported_move_notify,
|
||||
};
|
||||
|
||||
struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device,
|
||||
unsigned long offset,
|
||||
size_t size, int fd,
|
||||
int access)
|
||||
struct ib_umem_dmabuf *
|
||||
ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
|
||||
struct device *dma_device,
|
||||
unsigned long offset, size_t size,
|
||||
int fd, int access)
|
||||
{
|
||||
struct ib_umem_dmabuf *umem_dmabuf;
|
||||
int err;
|
||||
|
||||
umem_dmabuf = ib_umem_dmabuf_get(device, offset, size, fd, access,
|
||||
&ib_umem_dmabuf_attach_pinned_ops);
|
||||
umem_dmabuf = ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset,
|
||||
size, fd, access,
|
||||
&ib_umem_dmabuf_attach_pinned_ops);
|
||||
if (IS_ERR(umem_dmabuf))
|
||||
return umem_dmabuf;
|
||||
|
||||
@@ -217,17 +233,41 @@ err_release:
|
||||
ib_umem_release(&umem_dmabuf->umem);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device);
|
||||
|
||||
struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device,
|
||||
unsigned long offset,
|
||||
size_t size, int fd,
|
||||
int access)
|
||||
{
|
||||
return ib_umem_dmabuf_get_pinned_with_dma_device(device, device->dma_device,
|
||||
offset, size, fd, access);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned);
|
||||
|
||||
void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf)
|
||||
{
|
||||
struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
|
||||
|
||||
dma_resv_lock(dmabuf->resv, NULL);
|
||||
if (umem_dmabuf->revoked)
|
||||
goto end;
|
||||
ib_umem_dmabuf_unmap_pages(umem_dmabuf);
|
||||
if (umem_dmabuf->pinned) {
|
||||
dma_buf_unpin(umem_dmabuf->attach);
|
||||
umem_dmabuf->pinned = 0;
|
||||
}
|
||||
umem_dmabuf->revoked = 1;
|
||||
end:
|
||||
dma_resv_unlock(dmabuf->resv);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_dmabuf_revoke);
|
||||
|
||||
void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf)
|
||||
{
|
||||
struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
|
||||
|
||||
dma_resv_lock(dmabuf->resv, NULL);
|
||||
ib_umem_dmabuf_unmap_pages(umem_dmabuf);
|
||||
if (umem_dmabuf->pinned)
|
||||
dma_buf_unpin(umem_dmabuf->attach);
|
||||
dma_resv_unlock(dmabuf->resv);
|
||||
ib_umem_dmabuf_revoke(umem_dmabuf);
|
||||
|
||||
dma_buf_detach(dmabuf, umem_dmabuf->attach);
|
||||
dma_buf_put(dmabuf);
|
||||
|
||||
@@ -239,7 +239,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_REG_DMABUF_MR)(
|
||||
|
||||
mr = pd->device->ops.reg_user_mr_dmabuf(pd, offset, length, iova, fd,
|
||||
access_flags,
|
||||
&attrs->driver_udata);
|
||||
attrs);
|
||||
if (IS_ERR(mr))
|
||||
return PTR_ERR(mr);
|
||||
|
||||
|
||||
@@ -91,6 +91,15 @@ struct bnxt_re_ring_attr {
|
||||
u8 mode;
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structure and defines to handle
|
||||
* recovery
|
||||
*/
|
||||
#define BNXT_RE_PRE_RECOVERY_REMOVE 0x1
|
||||
#define BNXT_RE_COMPLETE_REMOVE 0x2
|
||||
#define BNXT_RE_POST_RECOVERY_INIT 0x4
|
||||
#define BNXT_RE_COMPLETE_INIT 0x8
|
||||
|
||||
struct bnxt_re_sqp_entries {
|
||||
struct bnxt_qplib_sge sge;
|
||||
u64 wrid;
|
||||
@@ -107,6 +116,11 @@ struct bnxt_re_gsi_context {
|
||||
struct bnxt_re_sqp_entries *sqp_tbl;
|
||||
};
|
||||
|
||||
struct bnxt_re_en_dev_info {
|
||||
struct bnxt_en_dev *en_dev;
|
||||
struct bnxt_re_dev *rdev;
|
||||
};
|
||||
|
||||
#define BNXT_RE_AEQ_IDX 0
|
||||
#define BNXT_RE_NQ_IDX 1
|
||||
#define BNXT_RE_GEN_P5_MAX_VF 64
|
||||
@@ -141,6 +155,7 @@ struct bnxt_re_pacing {
|
||||
#define BNXT_RE_GRC_FIFO_REG_BASE 0x2000
|
||||
|
||||
#define MAX_CQ_HASH_BITS (16)
|
||||
#define MAX_SRQ_HASH_BITS (16)
|
||||
struct bnxt_re_dev {
|
||||
struct ib_device ibdev;
|
||||
struct list_head list;
|
||||
@@ -154,6 +169,7 @@ struct bnxt_re_dev {
|
||||
#define BNXT_RE_FLAG_ERR_DEVICE_DETACHED 17
|
||||
#define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29
|
||||
struct net_device *netdev;
|
||||
struct auxiliary_device *adev;
|
||||
struct notifier_block nb;
|
||||
unsigned int version, major, minor;
|
||||
struct bnxt_qplib_chip_ctx *chip_ctx;
|
||||
@@ -196,6 +212,7 @@ struct bnxt_re_dev {
|
||||
struct work_struct dbq_fifo_check_work;
|
||||
struct delayed_work dbq_pacing_work;
|
||||
DECLARE_HASHTABLE(cq_hash, MAX_CQ_HASH_BITS);
|
||||
DECLARE_HASHTABLE(srq_hash, MAX_SRQ_HASH_BITS);
|
||||
};
|
||||
|
||||
#define to_bnxt_re_dev(ptr, member) \
|
||||
@@ -216,4 +233,10 @@ static inline struct device *rdev_to_dev(struct bnxt_re_dev *rdev)
|
||||
}
|
||||
|
||||
extern const struct uapi_definition bnxt_re_uapi_defs[];
|
||||
|
||||
static inline void bnxt_re_set_pacing_dev_state(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
rdev->qplib_res.pacing_data->dev_err_state =
|
||||
test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -115,6 +115,14 @@ static enum ib_access_flags __to_ib_access_flags(int qflags)
|
||||
return iflags;
|
||||
};
|
||||
|
||||
static void bnxt_re_check_and_set_relaxed_ordering(struct bnxt_re_dev *rdev,
|
||||
struct bnxt_qplib_mrw *qplib_mr)
|
||||
{
|
||||
if (_is_relaxed_ordering_supported(rdev->dev_attr.dev_cap_flags2) &&
|
||||
pcie_relaxed_ordering_enabled(rdev->en_dev->pdev))
|
||||
qplib_mr->flags |= CMDQ_REGISTER_MR_FLAGS_ENABLE_RO;
|
||||
}
|
||||
|
||||
static int bnxt_re_build_sgl(struct ib_sge *ib_sg_list,
|
||||
struct bnxt_qplib_sge *sg_list, int num)
|
||||
{
|
||||
@@ -517,15 +525,19 @@ static int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
|
||||
mr->rdev = rdev;
|
||||
mr->qplib_mr.pd = &pd->qplib_pd;
|
||||
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
|
||||
mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to alloc fence-HW-MR\n");
|
||||
goto fail;
|
||||
}
|
||||
mr->qplib_mr.access_flags = __from_ib_access_flags(mr_access_flags);
|
||||
if (!_is_alloc_mr_unified(rdev->dev_attr.dev_cap_flags)) {
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to alloc fence-HW-MR\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Register MR */
|
||||
mr->ib_mr.lkey = mr->qplib_mr.lkey;
|
||||
/* Register MR */
|
||||
mr->ib_mr.lkey = mr->qplib_mr.lkey;
|
||||
} else {
|
||||
mr->qplib_mr.flags = CMDQ_REGISTER_MR_FLAGS_ALLOC_MR;
|
||||
}
|
||||
mr->qplib_mr.va = (u64)(unsigned long)fence->va;
|
||||
mr->qplib_mr.total_size = BNXT_RE_FENCE_BYTES;
|
||||
rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, NULL,
|
||||
@@ -994,43 +1006,37 @@ static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp,
|
||||
align = sizeof(struct sq_send_hdr);
|
||||
ilsize = ALIGN(init_attr->cap.max_inline_data, align);
|
||||
|
||||
sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge);
|
||||
if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges))
|
||||
return -EINVAL;
|
||||
/* For gen p4 and gen p5 backward compatibility mode
|
||||
* wqe size is fixed to 128 bytes
|
||||
/* For gen p4 and gen p5 fixed wqe compatibility mode
|
||||
* wqe size is fixed to 128 bytes - ie 6 SGEs
|
||||
*/
|
||||
if (sq->wqe_size < bnxt_re_get_swqe_size(dev_attr->max_qp_sges) &&
|
||||
qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
|
||||
sq->wqe_size = bnxt_re_get_swqe_size(dev_attr->max_qp_sges);
|
||||
if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) {
|
||||
sq->wqe_size = bnxt_re_get_swqe_size(BNXT_STATIC_MAX_SGE);
|
||||
sq->max_sge = BNXT_STATIC_MAX_SGE;
|
||||
} else {
|
||||
sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge);
|
||||
if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (init_attr->cap.max_inline_data) {
|
||||
qplqp->max_inline_data = sq->wqe_size -
|
||||
sizeof(struct sq_send_hdr);
|
||||
init_attr->cap.max_inline_data = qplqp->max_inline_data;
|
||||
if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
|
||||
sq->max_sge = qplqp->max_inline_data /
|
||||
sizeof(struct sq_sge);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
|
||||
struct bnxt_re_qp *qp, struct ib_udata *udata)
|
||||
struct bnxt_re_qp *qp, struct bnxt_re_ucontext *cntx,
|
||||
struct bnxt_re_qp_req *ureq)
|
||||
{
|
||||
struct bnxt_qplib_qp *qplib_qp;
|
||||
struct bnxt_re_ucontext *cntx;
|
||||
struct bnxt_re_qp_req ureq;
|
||||
int bytes = 0, psn_sz;
|
||||
struct ib_umem *umem;
|
||||
int psn_nume;
|
||||
|
||||
qplib_qp = &qp->qplib_qp;
|
||||
cntx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext,
|
||||
ib_uctx);
|
||||
if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
|
||||
return -EFAULT;
|
||||
|
||||
bytes = (qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size);
|
||||
/* Consider mapping PSN search memory only for RC QPs. */
|
||||
@@ -1038,15 +1044,20 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
|
||||
psn_sz = bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ?
|
||||
sizeof(struct sq_psn_search_ext) :
|
||||
sizeof(struct sq_psn_search);
|
||||
psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
|
||||
qplib_qp->sq.max_wqe :
|
||||
((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) /
|
||||
sizeof(struct bnxt_qplib_sge));
|
||||
if (cntx && bnxt_re_is_var_size_supported(rdev, cntx)) {
|
||||
psn_nume = ureq->sq_slots;
|
||||
} else {
|
||||
psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
|
||||
qplib_qp->sq.max_wqe : ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) /
|
||||
sizeof(struct bnxt_qplib_sge));
|
||||
}
|
||||
if (_is_host_msn_table(rdev->qplib_res.dattr->dev_cap_flags2))
|
||||
psn_nume = roundup_pow_of_two(psn_nume);
|
||||
bytes += (psn_nume * psn_sz);
|
||||
}
|
||||
|
||||
bytes = PAGE_ALIGN(bytes);
|
||||
umem = ib_umem_get(&rdev->ibdev, ureq.qpsva, bytes,
|
||||
umem = ib_umem_get(&rdev->ibdev, ureq->qpsva, bytes,
|
||||
IB_ACCESS_LOCAL_WRITE);
|
||||
if (IS_ERR(umem))
|
||||
return PTR_ERR(umem);
|
||||
@@ -1055,12 +1066,12 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd,
|
||||
qplib_qp->sq.sg_info.umem = umem;
|
||||
qplib_qp->sq.sg_info.pgsize = PAGE_SIZE;
|
||||
qplib_qp->sq.sg_info.pgshft = PAGE_SHIFT;
|
||||
qplib_qp->qp_handle = ureq.qp_handle;
|
||||
qplib_qp->qp_handle = ureq->qp_handle;
|
||||
|
||||
if (!qp->qplib_qp.srq) {
|
||||
bytes = (qplib_qp->rq.max_wqe * qplib_qp->rq.wqe_size);
|
||||
bytes = PAGE_ALIGN(bytes);
|
||||
umem = ib_umem_get(&rdev->ibdev, ureq.qprva, bytes,
|
||||
umem = ib_umem_get(&rdev->ibdev, ureq->qprva, bytes,
|
||||
IB_ACCESS_LOCAL_WRITE);
|
||||
if (IS_ERR(umem))
|
||||
goto rqfail;
|
||||
@@ -1156,6 +1167,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
|
||||
/* Shadow QP SQ depth should be same as QP1 RQ depth */
|
||||
qp->qplib_qp.sq.wqe_size = bnxt_re_get_wqe_size(0, 6);
|
||||
qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
|
||||
qp->qplib_qp.sq.max_sw_wqe = qp1_qp->rq.max_wqe;
|
||||
qp->qplib_qp.sq.max_sge = 2;
|
||||
/* Q full delta can be 1 since it is internal QP */
|
||||
qp->qplib_qp.sq.q_full_delta = 1;
|
||||
@@ -1167,6 +1179,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
|
||||
|
||||
qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(6);
|
||||
qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
|
||||
qp->qplib_qp.rq.max_sw_wqe = qp1_qp->rq.max_wqe;
|
||||
qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
|
||||
/* Q full delta can be 1 since it is internal QP */
|
||||
qp->qplib_qp.rq.q_full_delta = 1;
|
||||
@@ -1228,6 +1241,7 @@ static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp,
|
||||
*/
|
||||
entries = bnxt_re_init_depth(init_attr->cap.max_recv_wr + 1, uctx);
|
||||
rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1);
|
||||
rq->max_sw_wqe = rq->max_wqe;
|
||||
rq->q_full_delta = 0;
|
||||
rq->sg_info.pgsize = PAGE_SIZE;
|
||||
rq->sg_info.pgshft = PAGE_SHIFT;
|
||||
@@ -1256,14 +1270,15 @@ static void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp)
|
||||
|
||||
static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
|
||||
struct ib_qp_init_attr *init_attr,
|
||||
struct bnxt_re_ucontext *uctx)
|
||||
struct bnxt_re_ucontext *uctx,
|
||||
struct bnxt_re_qp_req *ureq)
|
||||
{
|
||||
struct bnxt_qplib_dev_attr *dev_attr;
|
||||
struct bnxt_qplib_qp *qplqp;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_qplib_q *sq;
|
||||
int diff = 0;
|
||||
int entries;
|
||||
int diff;
|
||||
int rc;
|
||||
|
||||
rdev = qp->rdev;
|
||||
@@ -1272,21 +1287,28 @@ static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
|
||||
dev_attr = &rdev->dev_attr;
|
||||
|
||||
sq->max_sge = init_attr->cap.max_send_sge;
|
||||
if (sq->max_sge > dev_attr->max_qp_sges) {
|
||||
sq->max_sge = dev_attr->max_qp_sges;
|
||||
init_attr->cap.max_send_sge = sq->max_sge;
|
||||
}
|
||||
|
||||
rc = bnxt_re_setup_swqe_size(qp, init_attr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
entries = init_attr->cap.max_send_wr;
|
||||
/* Allocate 128 + 1 more than what's provided */
|
||||
diff = (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) ?
|
||||
0 : BNXT_QPLIB_RESERVED_QP_WRS;
|
||||
entries = bnxt_re_init_depth(entries + diff + 1, uctx);
|
||||
sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1);
|
||||
if (uctx && qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) {
|
||||
sq->max_wqe = ureq->sq_slots;
|
||||
sq->max_sw_wqe = ureq->sq_slots;
|
||||
sq->wqe_size = sizeof(struct sq_sge);
|
||||
} else {
|
||||
if (sq->max_sge > dev_attr->max_qp_sges) {
|
||||
sq->max_sge = dev_attr->max_qp_sges;
|
||||
init_attr->cap.max_send_sge = sq->max_sge;
|
||||
}
|
||||
|
||||
rc = bnxt_re_setup_swqe_size(qp, init_attr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Allocate 128 + 1 more than what's provided */
|
||||
diff = (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) ?
|
||||
0 : BNXT_QPLIB_RESERVED_QP_WRS;
|
||||
entries = bnxt_re_init_depth(entries + diff + 1, uctx);
|
||||
sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1);
|
||||
sq->max_sw_wqe = bnxt_qplib_get_depth(sq, qplqp->wqe_mode, true);
|
||||
}
|
||||
sq->q_full_delta = diff + 1;
|
||||
/*
|
||||
* Reserving one slot for Phantom WQE. Application can
|
||||
@@ -1349,10 +1371,10 @@ out:
|
||||
|
||||
static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
|
||||
struct ib_qp_init_attr *init_attr,
|
||||
struct ib_udata *udata)
|
||||
struct bnxt_re_ucontext *uctx,
|
||||
struct bnxt_re_qp_req *ureq)
|
||||
{
|
||||
struct bnxt_qplib_dev_attr *dev_attr;
|
||||
struct bnxt_re_ucontext *uctx;
|
||||
struct bnxt_qplib_qp *qplqp;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_re_cq *cq;
|
||||
@@ -1362,7 +1384,6 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
|
||||
qplqp = &qp->qplib_qp;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
|
||||
uctx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
|
||||
/* Setup misc params */
|
||||
ether_addr_copy(qplqp->smac, rdev->netdev->dev_addr);
|
||||
qplqp->pd = &pd->qplib_pd;
|
||||
@@ -1375,8 +1396,7 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
|
||||
goto out;
|
||||
}
|
||||
qplqp->type = (u8)qptype;
|
||||
qplqp->wqe_mode = rdev->chip_ctx->modes.wqe_mode;
|
||||
|
||||
qplqp->wqe_mode = bnxt_re_is_var_size_supported(rdev, uctx);
|
||||
if (init_attr->qp_type == IB_QPT_RC) {
|
||||
qplqp->max_rd_atomic = dev_attr->max_qp_rd_atom;
|
||||
qplqp->max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
|
||||
@@ -1411,14 +1431,14 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
|
||||
bnxt_re_adjust_gsi_rq_attr(qp);
|
||||
|
||||
/* Setup SQ */
|
||||
rc = bnxt_re_init_sq_attr(qp, init_attr, uctx);
|
||||
rc = bnxt_re_init_sq_attr(qp, init_attr, uctx, ureq);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (init_attr->qp_type == IB_QPT_GSI)
|
||||
bnxt_re_adjust_gsi_sq_attr(qp, init_attr, uctx);
|
||||
|
||||
if (udata) /* This will update DPI and qp_handle */
|
||||
rc = bnxt_re_init_user_qp(rdev, pd, qp, udata);
|
||||
if (uctx) /* This will update DPI and qp_handle */
|
||||
rc = bnxt_re_init_user_qp(rdev, pd, qp, uctx, ureq);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
@@ -1519,14 +1539,27 @@ static bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev,
|
||||
int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct ib_pd *ib_pd = ib_qp->pd;
|
||||
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
|
||||
struct bnxt_re_dev *rdev = pd->rdev;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
|
||||
struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
|
||||
struct bnxt_qplib_dev_attr *dev_attr;
|
||||
struct bnxt_re_ucontext *uctx;
|
||||
struct bnxt_re_qp_req ureq;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_re_pd *pd;
|
||||
struct bnxt_re_qp *qp;
|
||||
struct ib_pd *ib_pd;
|
||||
u32 active_qps;
|
||||
int rc;
|
||||
|
||||
ib_pd = ib_qp->pd;
|
||||
pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
|
||||
rdev = pd->rdev;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
|
||||
|
||||
uctx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
|
||||
if (udata)
|
||||
if (ib_copy_from_udata(&ureq, udata, min(udata->inlen, sizeof(ureq))))
|
||||
return -EFAULT;
|
||||
|
||||
rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
|
||||
if (!rc) {
|
||||
rc = -EINVAL;
|
||||
@@ -1534,7 +1567,7 @@ int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
|
||||
}
|
||||
|
||||
qp->rdev = rdev;
|
||||
rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
|
||||
rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, uctx, &ureq);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
@@ -1685,6 +1718,10 @@ int bnxt_re_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata)
|
||||
|
||||
if (qplib_srq->cq)
|
||||
nq = qplib_srq->cq->nq;
|
||||
if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
|
||||
free_page((unsigned long)srq->uctx_srq_page);
|
||||
hash_del(&srq->hash_entry);
|
||||
}
|
||||
bnxt_qplib_destroy_srq(&rdev->qplib_res, qplib_srq);
|
||||
ib_umem_release(srq->umem);
|
||||
atomic_dec(&rdev->stats.res.srq_count);
|
||||
@@ -1789,9 +1826,18 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
|
||||
}
|
||||
|
||||
if (udata) {
|
||||
struct bnxt_re_srq_resp resp;
|
||||
struct bnxt_re_srq_resp resp = {};
|
||||
|
||||
resp.srqid = srq->qplib_srq.id;
|
||||
if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT) {
|
||||
hash_add(rdev->srq_hash, &srq->hash_entry, srq->qplib_srq.id);
|
||||
srq->uctx_srq_page = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
if (!srq->uctx_srq_page) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
resp.comp_mask |= BNXT_RE_SRQ_TOGGLE_PAGE_SUPPORT;
|
||||
}
|
||||
rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "SRQ copy to udata failed!");
|
||||
@@ -2155,6 +2201,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
||||
entries = bnxt_re_init_depth(qp_attr->cap.max_recv_wr, uctx);
|
||||
qp->qplib_qp.rq.max_wqe =
|
||||
min_t(u32, entries, dev_attr->max_qp_wqes + 1);
|
||||
qp->qplib_qp.rq.max_sw_wqe = qp->qplib_qp.rq.max_wqe;
|
||||
qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
|
||||
qp_attr->cap.max_recv_wr;
|
||||
qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
|
||||
@@ -3845,9 +3892,12 @@ struct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags)
|
||||
|
||||
mr->rdev = rdev;
|
||||
mr->qplib_mr.pd = &pd->qplib_pd;
|
||||
mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
|
||||
mr->qplib_mr.access_flags = __from_ib_access_flags(mr_access_flags);
|
||||
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
|
||||
|
||||
if (mr_access_flags & IB_ACCESS_RELAXED_ORDERING)
|
||||
bnxt_re_check_and_set_relaxed_ordering(rdev, &mr->qplib_mr);
|
||||
|
||||
/* Allocate and register 0 as the address */
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc)
|
||||
@@ -3945,7 +3995,7 @@ struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type,
|
||||
|
||||
mr->rdev = rdev;
|
||||
mr->qplib_mr.pd = &pd->qplib_pd;
|
||||
mr->qplib_mr.flags = BNXT_QPLIB_FR_PMR;
|
||||
mr->qplib_mr.access_flags = BNXT_QPLIB_FR_PMR;
|
||||
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
|
||||
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
@@ -4062,21 +4112,28 @@ static struct ib_mr *__bnxt_re_user_reg_mr(struct ib_pd *ib_pd, u64 length, u64
|
||||
|
||||
mr->rdev = rdev;
|
||||
mr->qplib_mr.pd = &pd->qplib_pd;
|
||||
mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
|
||||
mr->qplib_mr.access_flags = __from_ib_access_flags(mr_access_flags);
|
||||
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR;
|
||||
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to allocate MR rc = %d", rc);
|
||||
rc = -EIO;
|
||||
goto free_mr;
|
||||
if (!_is_alloc_mr_unified(rdev->dev_attr.dev_cap_flags)) {
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to allocate MR rc = %d", rc);
|
||||
rc = -EIO;
|
||||
goto free_mr;
|
||||
}
|
||||
/* The fixed portion of the rkey is the same as the lkey */
|
||||
mr->ib_mr.rkey = mr->qplib_mr.rkey;
|
||||
} else {
|
||||
mr->qplib_mr.flags = CMDQ_REGISTER_MR_FLAGS_ALLOC_MR;
|
||||
}
|
||||
/* The fixed portion of the rkey is the same as the lkey */
|
||||
mr->ib_mr.rkey = mr->qplib_mr.rkey;
|
||||
mr->ib_umem = umem;
|
||||
mr->qplib_mr.va = virt_addr;
|
||||
mr->qplib_mr.total_size = length;
|
||||
|
||||
if (mr_access_flags & IB_ACCESS_RELAXED_ORDERING)
|
||||
bnxt_re_check_and_set_relaxed_ordering(rdev, &mr->qplib_mr);
|
||||
|
||||
umem_pgs = ib_umem_num_dma_blocks(umem, page_size);
|
||||
rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, umem,
|
||||
umem_pgs, page_size);
|
||||
@@ -4122,7 +4179,8 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
|
||||
|
||||
struct ib_mr *bnxt_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
|
||||
u64 length, u64 virt_addr, int fd,
|
||||
int mr_access_flags, struct ib_udata *udata)
|
||||
int mr_access_flags,
|
||||
struct uverbs_attr_bundle *attrs)
|
||||
{
|
||||
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
|
||||
struct bnxt_re_dev *rdev = pd->rdev;
|
||||
@@ -4187,9 +4245,6 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
|
||||
resp.cqe_sz = sizeof(struct cq_base);
|
||||
resp.max_cqd = dev_attr->max_cq_wqes;
|
||||
|
||||
resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE;
|
||||
resp.mode = rdev->chip_ctx->modes.wqe_mode;
|
||||
|
||||
if (rdev->chip_ctx->modes.db_push)
|
||||
resp.comp_mask |= BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED;
|
||||
|
||||
@@ -4211,7 +4266,13 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
|
||||
goto cfail;
|
||||
if (ureq.comp_mask & BNXT_RE_COMP_MASK_REQ_UCNTX_POW2_SUPPORT) {
|
||||
resp.comp_mask |= BNXT_RE_UCNTX_CMASK_POW2_DISABLED;
|
||||
uctx->cmask |= BNXT_RE_UCNTX_CMASK_POW2_DISABLED;
|
||||
uctx->cmask |= BNXT_RE_UCNTX_CAP_POW2_DISABLED;
|
||||
}
|
||||
if (ureq.comp_mask & BNXT_RE_COMP_MASK_REQ_UCNTX_VAR_WQE_SUPPORT) {
|
||||
resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE;
|
||||
resp.mode = rdev->chip_ctx->modes.wqe_mode;
|
||||
if (resp.mode == BNXT_QPLIB_WQE_MODE_VARIABLE)
|
||||
uctx->cmask |= BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4265,6 +4326,19 @@ static struct bnxt_re_cq *bnxt_re_search_for_cq(struct bnxt_re_dev *rdev, u32 cq
|
||||
return cq;
|
||||
}
|
||||
|
||||
static struct bnxt_re_srq *bnxt_re_search_for_srq(struct bnxt_re_dev *rdev, u32 srq_id)
|
||||
{
|
||||
struct bnxt_re_srq *srq = NULL, *tmp_srq;
|
||||
|
||||
hash_for_each_possible(rdev->srq_hash, tmp_srq, hash_entry, srq_id) {
|
||||
if (tmp_srq->qplib_srq.id == srq_id) {
|
||||
srq = tmp_srq;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return srq;
|
||||
}
|
||||
|
||||
/* Helper function to mmap the virtual memory from user app */
|
||||
int bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma)
|
||||
{
|
||||
@@ -4493,12 +4567,13 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
|
||||
struct bnxt_re_ucontext *uctx;
|
||||
struct ib_ucontext *ib_uctx;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_re_srq *srq;
|
||||
u32 length = PAGE_SIZE;
|
||||
struct bnxt_re_cq *cq;
|
||||
u64 mem_offset;
|
||||
u32 offset = 0;
|
||||
u64 addr = 0;
|
||||
u32 length;
|
||||
u32 offset;
|
||||
u32 cq_id;
|
||||
u32 res_id;
|
||||
int err;
|
||||
|
||||
ib_uctx = ib_uverbs_get_ucontext(attrs);
|
||||
@@ -4511,23 +4586,24 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
|
||||
|
||||
uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
|
||||
rdev = uctx->rdev;
|
||||
err = uverbs_copy_from(&res_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (res_type) {
|
||||
case BNXT_RE_CQ_TOGGLE_MEM:
|
||||
err = uverbs_copy_from(&cq_id, attrs, BNXT_RE_TOGGLE_MEM_RES_ID);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
cq = bnxt_re_search_for_cq(rdev, cq_id);
|
||||
cq = bnxt_re_search_for_cq(rdev, res_id);
|
||||
if (!cq)
|
||||
return -EINVAL;
|
||||
|
||||
length = PAGE_SIZE;
|
||||
addr = (u64)cq->uctx_cq_page;
|
||||
mmap_flag = BNXT_RE_MMAP_TOGGLE_PAGE;
|
||||
offset = 0;
|
||||
break;
|
||||
case BNXT_RE_SRQ_TOGGLE_MEM:
|
||||
srq = bnxt_re_search_for_srq(rdev, res_id);
|
||||
if (!srq)
|
||||
return -EINVAL;
|
||||
|
||||
addr = (u64)srq->uctx_srq_page;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -77,6 +77,8 @@ struct bnxt_re_srq {
|
||||
struct bnxt_qplib_srq qplib_srq;
|
||||
struct ib_umem *umem;
|
||||
spinlock_t lock; /* protect srq */
|
||||
void *uctx_srq_page;
|
||||
struct hlist_node hash_entry;
|
||||
};
|
||||
|
||||
struct bnxt_re_qp {
|
||||
@@ -171,12 +173,26 @@ static inline u16 bnxt_re_get_rwqe_size(int nsge)
|
||||
return sizeof(struct rq_wqe_hdr) + (nsge * sizeof(struct sq_sge));
|
||||
}
|
||||
|
||||
enum {
|
||||
BNXT_RE_UCNTX_CAP_POW2_DISABLED = 0x1ULL,
|
||||
BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED = 0x2ULL,
|
||||
};
|
||||
|
||||
static inline u32 bnxt_re_init_depth(u32 ent, struct bnxt_re_ucontext *uctx)
|
||||
{
|
||||
return uctx ? (uctx->cmask & BNXT_RE_UCNTX_CMASK_POW2_DISABLED) ?
|
||||
return uctx ? (uctx->cmask & BNXT_RE_UCNTX_CAP_POW2_DISABLED) ?
|
||||
ent : roundup_pow_of_two(ent) : ent;
|
||||
}
|
||||
|
||||
static inline bool bnxt_re_is_var_size_supported(struct bnxt_re_dev *rdev,
|
||||
struct bnxt_re_ucontext *uctx)
|
||||
{
|
||||
if (uctx)
|
||||
return uctx->cmask & BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED;
|
||||
else
|
||||
return rdev->chip_ctx->modes.wqe_mode;
|
||||
}
|
||||
|
||||
int bnxt_re_query_device(struct ib_device *ibdev,
|
||||
struct ib_device_attr *ib_attr,
|
||||
struct ib_udata *udata);
|
||||
@@ -242,7 +258,7 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
struct ib_mr *bnxt_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
|
||||
u64 length, u64 virt_addr,
|
||||
int fd, int mr_access_flags,
|
||||
struct ib_udata *udata);
|
||||
struct uverbs_attr_bundle *attrs);
|
||||
int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata);
|
||||
void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
|
||||
int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
|
||||
|
||||
@@ -83,11 +83,12 @@ static void bnxt_re_dev_stop(struct bnxt_re_dev *rdev);
|
||||
static int bnxt_re_netdev_event(struct notifier_block *notifier,
|
||||
unsigned long event, void *ptr);
|
||||
static struct bnxt_re_dev *bnxt_re_from_netdev(struct net_device *netdev);
|
||||
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev);
|
||||
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type);
|
||||
static int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev);
|
||||
|
||||
static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len,
|
||||
u32 *offset);
|
||||
static void bnxt_re_setup_cc(struct bnxt_re_dev *rdev, bool enable);
|
||||
static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct bnxt_qplib_chip_ctx *cctx;
|
||||
@@ -129,18 +130,20 @@ static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev)
|
||||
}
|
||||
}
|
||||
|
||||
static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode)
|
||||
static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct bnxt_qplib_chip_ctx *cctx;
|
||||
|
||||
cctx = rdev->chip_ctx;
|
||||
cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ?
|
||||
mode : BNXT_QPLIB_WQE_MODE_STATIC;
|
||||
cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ?
|
||||
BNXT_QPLIB_WQE_MODE_VARIABLE : BNXT_QPLIB_WQE_MODE_STATIC;
|
||||
if (bnxt_re_hwrm_qcaps(rdev))
|
||||
dev_err(rdev_to_dev(rdev),
|
||||
"Failed to query hwrm qcaps\n");
|
||||
if (bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx))
|
||||
if (bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx)) {
|
||||
cctx->modes.toggle_bits |= BNXT_QPLIB_CQ_TOGGLE_BIT;
|
||||
cctx->modes.toggle_bits |= BNXT_QPLIB_SRQ_TOGGLE_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev)
|
||||
@@ -158,7 +161,7 @@ static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev)
|
||||
kfree(chip_ctx);
|
||||
}
|
||||
|
||||
static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
||||
static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct bnxt_qplib_chip_ctx *chip_ctx;
|
||||
struct bnxt_en_dev *en_dev;
|
||||
@@ -166,6 +169,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
||||
|
||||
en_dev = rdev->en_dev;
|
||||
|
||||
rdev->qplib_res.pdev = en_dev->pdev;
|
||||
chip_ctx = kzalloc(sizeof(*chip_ctx), GFP_KERNEL);
|
||||
if (!chip_ctx)
|
||||
return -ENOMEM;
|
||||
@@ -180,7 +184,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
||||
rdev->qplib_res.dattr = &rdev->dev_attr;
|
||||
rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev);
|
||||
|
||||
bnxt_re_set_drv_mode(rdev, wqe_mode);
|
||||
bnxt_re_set_drv_mode(rdev);
|
||||
|
||||
bnxt_re_set_db_offset(rdev);
|
||||
rc = bnxt_qplib_map_db_bar(&rdev->qplib_res);
|
||||
@@ -290,21 +294,31 @@ static void bnxt_re_vf_res_config(struct bnxt_re_dev *rdev)
|
||||
|
||||
static void bnxt_re_shutdown(struct auxiliary_device *adev)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_re_dev *rdev;
|
||||
|
||||
if (!rdev)
|
||||
if (!en_info)
|
||||
return;
|
||||
|
||||
rdev = en_info->rdev;
|
||||
ib_unregister_device(&rdev->ibdev);
|
||||
bnxt_re_dev_uninit(rdev);
|
||||
bnxt_re_dev_uninit(rdev, BNXT_RE_COMPLETE_REMOVE);
|
||||
}
|
||||
|
||||
static void bnxt_re_stop_irq(void *handle)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = (struct bnxt_re_dev *)handle;
|
||||
struct bnxt_qplib_rcfw *rcfw = &rdev->rcfw;
|
||||
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle);
|
||||
struct bnxt_qplib_rcfw *rcfw;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_qplib_nq *nq;
|
||||
int indx;
|
||||
|
||||
if (!en_info)
|
||||
return;
|
||||
|
||||
rdev = en_info->rdev;
|
||||
rcfw = &rdev->rcfw;
|
||||
|
||||
for (indx = BNXT_RE_NQ_IDX; indx < rdev->num_msix; indx++) {
|
||||
nq = &rdev->nq[indx - 1];
|
||||
bnxt_qplib_nq_stop_irq(nq, false);
|
||||
@@ -315,12 +329,19 @@ static void bnxt_re_stop_irq(void *handle)
|
||||
|
||||
static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = (struct bnxt_re_dev *)handle;
|
||||
struct bnxt_msix_entry *msix_ent = rdev->en_dev->msix_entries;
|
||||
struct bnxt_qplib_rcfw *rcfw = &rdev->rcfw;
|
||||
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle);
|
||||
struct bnxt_msix_entry *msix_ent;
|
||||
struct bnxt_qplib_rcfw *rcfw;
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_qplib_nq *nq;
|
||||
int indx, rc;
|
||||
|
||||
if (!en_info)
|
||||
return;
|
||||
|
||||
rdev = en_info->rdev;
|
||||
msix_ent = rdev->en_dev->msix_entries;
|
||||
rcfw = &rdev->rcfw;
|
||||
if (!ent) {
|
||||
/* Not setting the f/w timeout bit in rcfw.
|
||||
* During the driver unload the first command
|
||||
@@ -365,14 +386,9 @@ static struct bnxt_ulp_ops bnxt_re_ulp_ops = {
|
||||
static int bnxt_re_register_netdev(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct bnxt_en_dev *en_dev;
|
||||
int rc;
|
||||
|
||||
en_dev = rdev->en_dev;
|
||||
|
||||
rc = bnxt_register_dev(en_dev, &bnxt_re_ulp_ops, rdev);
|
||||
if (!rc)
|
||||
rdev->qplib_res.pdev = rdev->en_dev->pdev;
|
||||
return rc;
|
||||
return bnxt_register_dev(en_dev, &bnxt_re_ulp_ops, rdev->adev);
|
||||
}
|
||||
|
||||
static void bnxt_re_init_hwrm_hdr(struct input *hdr, u16 opcd)
|
||||
@@ -1573,7 +1589,7 @@ static int bnxt_re_ib_init(struct bnxt_re_dev *rdev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev)
|
||||
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
{
|
||||
u8 type;
|
||||
int rc;
|
||||
@@ -1606,8 +1622,10 @@ static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev)
|
||||
bnxt_re_deinitialize_dbr_pacing(rdev);
|
||||
|
||||
bnxt_re_destroy_chip_ctx(rdev);
|
||||
if (test_and_clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags))
|
||||
bnxt_unregister_dev(rdev->en_dev);
|
||||
if (op_type == BNXT_RE_COMPLETE_REMOVE) {
|
||||
if (test_and_clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags))
|
||||
bnxt_unregister_dev(rdev->en_dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* worker thread for polling periodic events. Now used for QoS programming*/
|
||||
@@ -1620,7 +1638,7 @@ static void bnxt_re_worker(struct work_struct *work)
|
||||
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
|
||||
}
|
||||
|
||||
static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
||||
static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
{
|
||||
struct bnxt_re_ring_attr rattr = {};
|
||||
struct bnxt_qplib_creq_ctx *creq;
|
||||
@@ -1629,16 +1647,18 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
||||
u8 type;
|
||||
int rc;
|
||||
|
||||
/* Registered a new RoCE device instance to netdev */
|
||||
rc = bnxt_re_register_netdev(rdev);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev,
|
||||
"Failed to register with netedev: %#x\n", rc);
|
||||
return -EINVAL;
|
||||
if (op_type == BNXT_RE_COMPLETE_INIT) {
|
||||
/* Registered a new RoCE device instance to netdev */
|
||||
rc = bnxt_re_register_netdev(rdev);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev,
|
||||
"Failed to register with netedev: %#x\n", rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
||||
|
||||
rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode);
|
||||
rc = bnxt_re_setup_chip_ctx(rdev);
|
||||
if (rc) {
|
||||
bnxt_unregister_dev(rdev->en_dev);
|
||||
clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
||||
@@ -1771,6 +1791,8 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
||||
bnxt_re_vf_res_config(rdev);
|
||||
}
|
||||
hash_init(rdev->cq_hash);
|
||||
if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT)
|
||||
hash_init(rdev->srq_hash);
|
||||
|
||||
return 0;
|
||||
free_sctx:
|
||||
@@ -1785,21 +1807,38 @@ free_ring:
|
||||
free_rcfw:
|
||||
bnxt_qplib_free_rcfw_channel(&rdev->rcfw);
|
||||
fail:
|
||||
bnxt_re_dev_uninit(rdev);
|
||||
bnxt_re_dev_uninit(rdev, BNXT_RE_COMPLETE_REMOVE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode)
|
||||
static void bnxt_re_update_en_info_rdev(struct bnxt_re_dev *rdev,
|
||||
struct bnxt_re_en_dev_info *en_info,
|
||||
struct auxiliary_device *adev)
|
||||
{
|
||||
/* Before updating the rdev pointer in bnxt_re_en_dev_info structure,
|
||||
* take the rtnl lock to avoid accessing invalid rdev pointer from
|
||||
* L2 ULP callbacks. This is applicable in all the places where rdev
|
||||
* pointer is updated in bnxt_re_en_dev_info.
|
||||
*/
|
||||
rtnl_lock();
|
||||
en_info->rdev = rdev;
|
||||
rdev->adev = adev;
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static int bnxt_re_add_device(struct auxiliary_device *adev, u8 op_type)
|
||||
{
|
||||
struct bnxt_aux_priv *aux_priv =
|
||||
container_of(adev, struct bnxt_aux_priv, aux_dev);
|
||||
struct bnxt_re_en_dev_info *en_info;
|
||||
struct bnxt_en_dev *en_dev;
|
||||
struct bnxt_re_dev *rdev;
|
||||
int rc;
|
||||
|
||||
/* en_dev should never be NULL as long as adev and aux_dev are valid. */
|
||||
en_dev = aux_priv->edev;
|
||||
en_info = auxiliary_get_drvdata(adev);
|
||||
en_dev = en_info->en_dev;
|
||||
|
||||
|
||||
rdev = bnxt_re_dev_add(aux_priv, en_dev);
|
||||
if (!rdev || !rdev_to_dev(rdev)) {
|
||||
@@ -1807,7 +1846,9 @@ static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = bnxt_re_dev_init(rdev, wqe_mode);
|
||||
bnxt_re_update_en_info_rdev(rdev, en_info, adev);
|
||||
|
||||
rc = bnxt_re_dev_init(rdev, op_type);
|
||||
if (rc)
|
||||
goto re_dev_dealloc;
|
||||
|
||||
@@ -1817,12 +1858,22 @@ static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode)
|
||||
aux_priv->aux_dev.name);
|
||||
goto re_dev_uninit;
|
||||
}
|
||||
auxiliary_set_drvdata(adev, rdev);
|
||||
|
||||
rdev->nb.notifier_call = bnxt_re_netdev_event;
|
||||
rc = register_netdevice_notifier(&rdev->nb);
|
||||
if (rc) {
|
||||
rdev->nb.notifier_call = NULL;
|
||||
pr_err("%s: Cannot register to netdevice_notifier",
|
||||
ROCE_DRV_MODULE_NAME);
|
||||
return rc;
|
||||
}
|
||||
bnxt_re_setup_cc(rdev, true);
|
||||
|
||||
return 0;
|
||||
|
||||
re_dev_uninit:
|
||||
bnxt_re_dev_uninit(rdev);
|
||||
bnxt_re_update_en_info_rdev(NULL, en_info, adev);
|
||||
bnxt_re_dev_uninit(rdev, BNXT_RE_COMPLETE_REMOVE);
|
||||
re_dev_dealloc:
|
||||
ib_dealloc_device(&rdev->ibdev);
|
||||
exit:
|
||||
@@ -1905,14 +1956,9 @@ exit:
|
||||
|
||||
#define BNXT_ADEV_NAME "bnxt_en"
|
||||
|
||||
static void bnxt_re_remove(struct auxiliary_device *adev)
|
||||
static void bnxt_re_remove_device(struct bnxt_re_dev *rdev, u8 op_type,
|
||||
struct auxiliary_device *aux_dev)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = auxiliary_get_drvdata(adev);
|
||||
|
||||
if (!rdev)
|
||||
return;
|
||||
|
||||
mutex_lock(&bnxt_re_mutex);
|
||||
if (rdev->nb.notifier_call) {
|
||||
unregister_netdevice_notifier(&rdev->nb);
|
||||
rdev->nb.notifier_call = NULL;
|
||||
@@ -1920,41 +1966,56 @@ static void bnxt_re_remove(struct auxiliary_device *adev)
|
||||
/* If notifier is null, we should have already done a
|
||||
* clean up before coming here.
|
||||
*/
|
||||
goto skip_remove;
|
||||
return;
|
||||
}
|
||||
bnxt_re_setup_cc(rdev, false);
|
||||
ib_unregister_device(&rdev->ibdev);
|
||||
bnxt_re_dev_uninit(rdev);
|
||||
bnxt_re_dev_uninit(rdev, op_type);
|
||||
ib_dealloc_device(&rdev->ibdev);
|
||||
skip_remove:
|
||||
}
|
||||
|
||||
static void bnxt_re_remove(struct auxiliary_device *adev)
|
||||
{
|
||||
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_re_dev *rdev;
|
||||
|
||||
mutex_lock(&bnxt_re_mutex);
|
||||
if (!en_info) {
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
return;
|
||||
}
|
||||
rdev = en_info->rdev;
|
||||
|
||||
if (rdev)
|
||||
bnxt_re_remove_device(rdev, BNXT_RE_COMPLETE_REMOVE, adev);
|
||||
kfree(en_info);
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
}
|
||||
|
||||
static int bnxt_re_probe(struct auxiliary_device *adev,
|
||||
const struct auxiliary_device_id *id)
|
||||
{
|
||||
struct bnxt_re_dev *rdev;
|
||||
struct bnxt_aux_priv *aux_priv =
|
||||
container_of(adev, struct bnxt_aux_priv, aux_dev);
|
||||
struct bnxt_re_en_dev_info *en_info;
|
||||
struct bnxt_en_dev *en_dev;
|
||||
int rc;
|
||||
|
||||
en_dev = aux_priv->edev;
|
||||
|
||||
mutex_lock(&bnxt_re_mutex);
|
||||
rc = bnxt_re_add_device(adev, BNXT_QPLIB_WQE_MODE_STATIC);
|
||||
if (rc) {
|
||||
en_info = kzalloc(sizeof(*en_info), GFP_KERNEL);
|
||||
if (!en_info) {
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
return rc;
|
||||
return -ENOMEM;
|
||||
}
|
||||
en_info->en_dev = en_dev;
|
||||
|
||||
rdev = auxiliary_get_drvdata(adev);
|
||||
auxiliary_set_drvdata(adev, en_info);
|
||||
|
||||
rdev->nb.notifier_call = bnxt_re_netdev_event;
|
||||
rc = register_netdevice_notifier(&rdev->nb);
|
||||
if (rc) {
|
||||
rdev->nb.notifier_call = NULL;
|
||||
pr_err("%s: Cannot register to netdevice_notifier",
|
||||
ROCE_DRV_MODULE_NAME);
|
||||
rc = bnxt_re_add_device(adev, BNXT_RE_COMPLETE_INIT);
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
bnxt_re_setup_cc(rdev, true);
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
return 0;
|
||||
|
||||
@@ -1967,11 +2028,15 @@ err:
|
||||
|
||||
static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_en_dev *en_dev;
|
||||
struct bnxt_re_dev *rdev;
|
||||
|
||||
if (!rdev)
|
||||
if (!en_info)
|
||||
return 0;
|
||||
|
||||
rdev = en_info->rdev;
|
||||
en_dev = en_info->en_dev;
|
||||
mutex_lock(&bnxt_re_mutex);
|
||||
/* L2 driver may invoke this callback during device error/crash or device
|
||||
* reset. Current RoCE driver doesn't recover the device in case of
|
||||
@@ -1990,13 +2055,20 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
|
||||
set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags);
|
||||
|
||||
bnxt_re_dev_stop(rdev);
|
||||
bnxt_re_stop_irq(rdev);
|
||||
bnxt_re_stop_irq(adev);
|
||||
/* Move the device states to detached and avoid sending any more
|
||||
* commands to HW
|
||||
*/
|
||||
set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
|
||||
set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags);
|
||||
wake_up_all(&rdev->rcfw.cmdq.waitq);
|
||||
|
||||
if (rdev->pacing.dbr_pacing)
|
||||
bnxt_re_set_pacing_dev_state(rdev);
|
||||
|
||||
ibdev_info(&rdev->ibdev, "%s: L2 driver notified to stop en_state 0x%lx",
|
||||
__func__, en_dev->en_state);
|
||||
bnxt_re_remove_device(rdev, BNXT_RE_PRE_RECOVERY_REMOVE, adev);
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -2004,9 +2076,10 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
|
||||
|
||||
static int bnxt_re_resume(struct auxiliary_device *adev)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev);
|
||||
struct bnxt_re_dev *rdev;
|
||||
|
||||
if (!rdev)
|
||||
if (!en_info)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&bnxt_re_mutex);
|
||||
@@ -2017,7 +2090,9 @@ static int bnxt_re_resume(struct auxiliary_device *adev)
|
||||
* L2 driver want to modify the MSIx table.
|
||||
*/
|
||||
|
||||
ibdev_info(&rdev->ibdev, "Handle device resume call");
|
||||
bnxt_re_add_device(adev, BNXT_RE_POST_RECOVERY_INIT);
|
||||
rdev = en_info->rdev;
|
||||
ibdev_info(&rdev->ibdev, "Device resume completed");
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -54,6 +54,10 @@
|
||||
#include "qplib_rcfw.h"
|
||||
#include "qplib_sp.h"
|
||||
#include "qplib_fp.h"
|
||||
#include <rdma/ib_addr.h>
|
||||
#include "bnxt_ulp.h"
|
||||
#include "bnxt_re.h"
|
||||
#include "ib_verbs.h"
|
||||
|
||||
static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp);
|
||||
|
||||
@@ -347,6 +351,7 @@ static void bnxt_qplib_service_nq(struct tasklet_struct *t)
|
||||
case NQ_BASE_TYPE_SRQ_EVENT:
|
||||
{
|
||||
struct bnxt_qplib_srq *srq;
|
||||
struct bnxt_re_srq *srq_p;
|
||||
struct nq_srq_event *nqsrqe =
|
||||
(struct nq_srq_event *)nqe;
|
||||
|
||||
@@ -354,6 +359,12 @@ static void bnxt_qplib_service_nq(struct tasklet_struct *t)
|
||||
q_handle |= (u64)le32_to_cpu(nqsrqe->srq_handle_high)
|
||||
<< 32;
|
||||
srq = (struct bnxt_qplib_srq *)q_handle;
|
||||
srq->toggle = (le16_to_cpu(nqe->info10_type) & NQ_CN_TOGGLE_MASK)
|
||||
>> NQ_CN_TOGGLE_SFT;
|
||||
srq->dbinfo.toggle = srq->toggle;
|
||||
srq_p = container_of(srq, struct bnxt_re_srq, qplib_srq);
|
||||
if (srq_p->uctx_srq_page)
|
||||
*((u32 *)srq_p->uctx_srq_page) = srq->toggle;
|
||||
bnxt_qplib_armen_db(&srq->dbinfo,
|
||||
DBC_DBC_TYPE_SRQ_ARMENA);
|
||||
if (nq->srqn_handler(nq,
|
||||
@@ -809,13 +820,13 @@ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que)
|
||||
{
|
||||
int indx;
|
||||
|
||||
que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL);
|
||||
que->swq = kcalloc(que->max_sw_wqe, sizeof(*que->swq), GFP_KERNEL);
|
||||
if (!que->swq)
|
||||
return -ENOMEM;
|
||||
|
||||
que->swq_start = 0;
|
||||
que->swq_last = que->max_wqe - 1;
|
||||
for (indx = 0; indx < que->max_wqe; indx++)
|
||||
que->swq_last = que->max_sw_wqe - 1;
|
||||
for (indx = 0; indx < que->max_sw_wqe; indx++)
|
||||
que->swq[indx].next_idx = indx + 1;
|
||||
que->swq[que->swq_last].next_idx = 0; /* Make it circular */
|
||||
que->swq_last = 0;
|
||||
@@ -851,7 +862,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
||||
hwq_attr.res = res;
|
||||
hwq_attr.sginfo = &sq->sg_info;
|
||||
hwq_attr.stride = sizeof(struct sq_sge);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(sq);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, false);
|
||||
hwq_attr.type = HWQ_TYPE_QUEUE;
|
||||
rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr);
|
||||
if (rc)
|
||||
@@ -879,7 +890,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
||||
hwq_attr.res = res;
|
||||
hwq_attr.sginfo = &rq->sg_info;
|
||||
hwq_attr.stride = sizeof(struct sq_sge);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(rq);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false);
|
||||
hwq_attr.type = HWQ_TYPE_QUEUE;
|
||||
rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr);
|
||||
if (rc)
|
||||
@@ -1011,7 +1022,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
||||
hwq_attr.res = res;
|
||||
hwq_attr.sginfo = &sq->sg_info;
|
||||
hwq_attr.stride = sizeof(struct sq_sge);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(sq);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, true);
|
||||
hwq_attr.aux_stride = psn_sz;
|
||||
hwq_attr.aux_depth = psn_sz ? bnxt_qplib_set_sq_size(sq, qp->wqe_mode)
|
||||
: 0;
|
||||
@@ -1052,7 +1063,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
||||
hwq_attr.res = res;
|
||||
hwq_attr.sginfo = &rq->sg_info;
|
||||
hwq_attr.stride = sizeof(struct sq_sge);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(rq);
|
||||
hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false);
|
||||
hwq_attr.aux_stride = 0;
|
||||
hwq_attr.aux_depth = 0;
|
||||
hwq_attr.type = HWQ_TYPE_QUEUE;
|
||||
@@ -2471,6 +2482,32 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_qplib_get_cqe_sq_cons(struct bnxt_qplib_q *sq, u32 cqe_slot)
|
||||
{
|
||||
struct bnxt_qplib_hwq *sq_hwq;
|
||||
struct bnxt_qplib_swq *swq;
|
||||
int cqe_sq_cons = -1;
|
||||
u32 start, last;
|
||||
|
||||
sq_hwq = &sq->hwq;
|
||||
|
||||
start = sq->swq_start;
|
||||
last = sq->swq_last;
|
||||
|
||||
while (last != start) {
|
||||
swq = &sq->swq[last];
|
||||
if (swq->slot_idx == cqe_slot) {
|
||||
cqe_sq_cons = swq->next_idx;
|
||||
dev_err(&sq_hwq->pdev->dev, "%s: Found cons wqe = %d slot = %d\n",
|
||||
__func__, cqe_sq_cons, cqe_slot);
|
||||
break;
|
||||
}
|
||||
|
||||
last = swq->next_idx;
|
||||
}
|
||||
return cqe_sq_cons;
|
||||
}
|
||||
|
||||
static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
|
||||
struct cq_req *hwcqe,
|
||||
struct bnxt_qplib_cqe **pcqe, int *budget,
|
||||
@@ -2478,9 +2515,10 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
|
||||
{
|
||||
struct bnxt_qplib_swq *swq;
|
||||
struct bnxt_qplib_cqe *cqe;
|
||||
u32 cqe_sq_cons, slot_num;
|
||||
struct bnxt_qplib_qp *qp;
|
||||
struct bnxt_qplib_q *sq;
|
||||
u32 cqe_sq_cons;
|
||||
int cqe_cons;
|
||||
int rc = 0;
|
||||
|
||||
qp = (struct bnxt_qplib_qp *)((unsigned long)
|
||||
@@ -2492,12 +2530,26 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
|
||||
}
|
||||
sq = &qp->sq;
|
||||
|
||||
cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_wqe;
|
||||
cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_sw_wqe;
|
||||
if (qp->sq.flushed) {
|
||||
dev_dbg(&cq->hwq.pdev->dev,
|
||||
"%s: QP in Flush QP = %p\n", __func__, qp);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (__is_err_cqe_for_var_wqe(qp, hwcqe->status)) {
|
||||
slot_num = le16_to_cpu(hwcqe->sq_cons_idx);
|
||||
cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, slot_num);
|
||||
if (cqe_cons < 0) {
|
||||
dev_err(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n",
|
||||
__func__, slot_num);
|
||||
goto done;
|
||||
}
|
||||
cqe_sq_cons = cqe_cons;
|
||||
dev_err(&cq->hwq.pdev->dev, "%s: cqe_sq_cons = %d swq_last = %d swq_start = %d\n",
|
||||
__func__, cqe_sq_cons, sq->swq_last, sq->swq_start);
|
||||
}
|
||||
|
||||
/* Require to walk the sq's swq to fabricate CQEs for all previously
|
||||
* signaled SWQEs due to CQE aggregation from the current sq cons
|
||||
* to the cqe_sq_cons
|
||||
@@ -2882,7 +2934,7 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq,
|
||||
cqe_cons = le16_to_cpu(hwcqe->sq_cons_idx);
|
||||
if (cqe_cons == 0xFFFF)
|
||||
goto do_rq;
|
||||
cqe_cons %= sq->max_wqe;
|
||||
cqe_cons %= sq->max_sw_wqe;
|
||||
|
||||
if (qp->sq.flushed) {
|
||||
dev_dbg(&cq->hwq.pdev->dev,
|
||||
|
||||
@@ -105,6 +105,7 @@ struct bnxt_qplib_srq {
|
||||
struct bnxt_qplib_sg_info sg_info;
|
||||
u16 eventq_hw_ring_id;
|
||||
spinlock_t lock; /* protect SRQE link list */
|
||||
u8 toggle;
|
||||
};
|
||||
|
||||
struct bnxt_qplib_sge {
|
||||
@@ -251,6 +252,7 @@ struct bnxt_qplib_q {
|
||||
struct bnxt_qplib_db_info dbinfo;
|
||||
struct bnxt_qplib_sg_info sg_info;
|
||||
u32 max_wqe;
|
||||
u32 max_sw_wqe;
|
||||
u16 wqe_size;
|
||||
u16 q_full_delta;
|
||||
u16 max_sge;
|
||||
@@ -586,15 +588,22 @@ static inline void bnxt_qplib_swq_mod_start(struct bnxt_qplib_q *que, u32 idx)
|
||||
que->swq_start = que->swq[idx].next_idx;
|
||||
}
|
||||
|
||||
static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que)
|
||||
static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que, u8 wqe_mode, bool is_sq)
|
||||
{
|
||||
return (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge);
|
||||
u32 slots;
|
||||
|
||||
/* Queue depth is the number of slots. */
|
||||
slots = (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge);
|
||||
/* For variable WQE mode, need to align the slots to 256 */
|
||||
if (wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE && is_sq)
|
||||
slots = ALIGN(slots, BNXT_VAR_MAX_SLOT_ALIGN);
|
||||
return slots;
|
||||
}
|
||||
|
||||
static inline u32 bnxt_qplib_set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode)
|
||||
{
|
||||
return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
|
||||
que->max_wqe : bnxt_qplib_get_depth(que);
|
||||
que->max_wqe : bnxt_qplib_get_depth(que, wqe_mode, true);
|
||||
}
|
||||
|
||||
static inline u32 bnxt_qplib_set_sq_max_slot(u8 wqe_mode)
|
||||
@@ -641,4 +650,14 @@ static inline __le64 bnxt_re_update_msn_tbl(u32 st_idx, u32 npsn, u32 start_psn)
|
||||
(((start_psn) << SQ_MSN_SEARCH_START_PSN_SFT) &
|
||||
SQ_MSN_SEARCH_START_PSN_MASK));
|
||||
}
|
||||
|
||||
static inline bool __is_var_wqe(struct bnxt_qplib_qp *qp)
|
||||
{
|
||||
return (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE);
|
||||
}
|
||||
|
||||
static inline bool __is_err_cqe_for_var_wqe(struct bnxt_qplib_qp *qp, u8 status)
|
||||
{
|
||||
return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp);
|
||||
}
|
||||
#endif /* __BNXT_QPLIB_FP_H__ */
|
||||
|
||||
@@ -82,6 +82,7 @@ struct bnxt_qplib_db_pacing_data {
|
||||
u32 fifo_room_mask;
|
||||
u32 fifo_room_shift;
|
||||
u32 grc_reg_offset;
|
||||
u32 dev_err_state;
|
||||
};
|
||||
|
||||
#define BNXT_QPLIB_DBR_PF_DB_OFFSET 0x10000
|
||||
@@ -565,4 +566,14 @@ static inline u8 bnxt_qplib_dbr_pacing_en(struct bnxt_qplib_chip_ctx *cctx)
|
||||
return cctx->modes.dbr_pacing;
|
||||
}
|
||||
|
||||
static inline bool _is_alloc_mr_unified(u16 dev_cap_flags)
|
||||
{
|
||||
return dev_cap_flags & CREQ_QUERY_FUNC_RESP_SB_MR_REGISTER_ALLOC;
|
||||
}
|
||||
|
||||
static inline bool _is_relaxed_ordering_supported(u16 dev_cap_ext_flags2)
|
||||
{
|
||||
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif /* __BNXT_QPLIB_RES_H__ */
|
||||
|
||||
@@ -95,11 +95,13 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
||||
struct bnxt_qplib_cmdqmsg msg = {};
|
||||
struct creq_query_func_resp_sb *sb;
|
||||
struct bnxt_qplib_rcfw_sbuf sbuf;
|
||||
struct bnxt_qplib_chip_ctx *cctx;
|
||||
struct cmdq_query_func req = {};
|
||||
u8 *tqm_alloc;
|
||||
int i, rc;
|
||||
u32 temp;
|
||||
|
||||
cctx = rcfw->res->cctx;
|
||||
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
|
||||
CMDQ_BASE_OPCODE_QUERY_FUNC,
|
||||
sizeof(req));
|
||||
@@ -133,8 +135,9 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
||||
* reporting the max number
|
||||
*/
|
||||
attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
|
||||
attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx) ?
|
||||
6 : sb->max_sge;
|
||||
|
||||
attr->max_qp_sges = cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE ?
|
||||
min_t(u32, sb->max_sge_var_wqe, BNXT_VAR_MAX_SGE) : 6;
|
||||
attr->max_cq = le32_to_cpu(sb->max_cq);
|
||||
attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
|
||||
attr->max_cq_sges = attr->max_qp_sges;
|
||||
@@ -541,7 +544,7 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
|
||||
req.pd_id = cpu_to_le32(mrw->pd->id);
|
||||
req.mrw_flags = mrw->type;
|
||||
if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR &&
|
||||
mrw->flags & BNXT_QPLIB_FR_PMR) ||
|
||||
mrw->access_flags & BNXT_QPLIB_FR_PMR) ||
|
||||
mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A ||
|
||||
mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)
|
||||
req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY;
|
||||
@@ -653,9 +656,12 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
|
||||
req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) <<
|
||||
CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) &
|
||||
CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK));
|
||||
req.access = (mr->flags & 0xFFFF);
|
||||
req.access = (mr->access_flags & 0xFFFF);
|
||||
req.va = cpu_to_le64(mr->va);
|
||||
req.key = cpu_to_le32(mr->lkey);
|
||||
if (_is_alloc_mr_unified(res->dattr->dev_cap_flags))
|
||||
req.key = cpu_to_le32(mr->pd->id);
|
||||
req.flags = cpu_to_le16(mr->flags);
|
||||
req.mr_size = cpu_to_le64(mr->total_size);
|
||||
|
||||
bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
|
||||
@@ -664,6 +670,11 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
if (_is_alloc_mr_unified(res->dattr->dev_cap_flags)) {
|
||||
mr->lkey = le32_to_cpu(resp.xid);
|
||||
mr->rkey = mr->lkey;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#ifndef __BNXT_QPLIB_SP_H__
|
||||
#define __BNXT_QPLIB_SP_H__
|
||||
|
||||
#include <rdma/bnxt_re-abi.h>
|
||||
#define BNXT_QPLIB_RESERVED_QP_WRS 128
|
||||
|
||||
struct bnxt_qplib_dev_attr {
|
||||
@@ -108,7 +109,7 @@ struct bnxt_qplib_ah {
|
||||
struct bnxt_qplib_mrw {
|
||||
struct bnxt_qplib_pd *pd;
|
||||
int type;
|
||||
u32 flags;
|
||||
u32 access_flags;
|
||||
#define BNXT_QPLIB_FR_PMR 0x80000000
|
||||
u32 lkey;
|
||||
u32 rkey;
|
||||
@@ -116,6 +117,7 @@ struct bnxt_qplib_mrw {
|
||||
u64 va;
|
||||
u64 total_size;
|
||||
u32 npages;
|
||||
u16 flags;
|
||||
u64 mr_handle;
|
||||
struct bnxt_qplib_hwq hwq;
|
||||
};
|
||||
@@ -351,4 +353,11 @@ int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid,
|
||||
int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res,
|
||||
struct bnxt_qplib_cc_param *cc_param);
|
||||
|
||||
#define BNXT_VAR_MAX_WQE 4352
|
||||
#define BNXT_VAR_MAX_SLOT_ALIGN 256
|
||||
#define BNXT_VAR_MAX_SGE 13
|
||||
#define BNXT_RE_MAX_RQ_WQES 65536
|
||||
|
||||
#define BNXT_STATIC_MAX_SGE 6
|
||||
|
||||
#endif /* __BNXT_QPLIB_SP_H__*/
|
||||
|
||||
@@ -409,7 +409,7 @@ struct creq_deinitialize_fw_resp {
|
||||
u8 reserved48[6];
|
||||
};
|
||||
|
||||
/* cmdq_create_qp (size:768b/96B) */
|
||||
/* cmdq_create_qp (size:832b/104B) */
|
||||
struct cmdq_create_qp {
|
||||
u8 opcode;
|
||||
#define CMDQ_CREATE_QP_OPCODE_CREATE_QP 0x1UL
|
||||
@@ -430,8 +430,11 @@ struct cmdq_create_qp {
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_OPTIMIZED_TRANSMIT_ENABLED 0x20UL
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_RESPONDER_UD_CQE_WITH_CFA 0x40UL
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED 0x80UL
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_EXPRESS_MODE_ENABLED 0x100UL
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_STEERING_TAG_VALID 0x200UL
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_RDMA_READ_OR_ATOMICS_USED 0x400UL
|
||||
#define CMDQ_CREATE_QP_QP_FLAGS_LAST \
|
||||
CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED
|
||||
CMDQ_CREATE_QP_QP_FLAGS_RDMA_READ_OR_ATOMICS_USED
|
||||
u8 type;
|
||||
#define CMDQ_CREATE_QP_TYPE_RC 0x2UL
|
||||
#define CMDQ_CREATE_QP_TYPE_UD 0x4UL
|
||||
@@ -492,6 +495,9 @@ struct cmdq_create_qp {
|
||||
__le64 rq_pbl;
|
||||
__le64 irrq_addr;
|
||||
__le64 orrq_addr;
|
||||
__le32 request_xid;
|
||||
__le16 steering_tag;
|
||||
__le16 reserved16;
|
||||
};
|
||||
|
||||
/* creq_create_qp_resp (size:128b/16B) */
|
||||
@@ -972,13 +978,14 @@ struct creq_query_qp_extend_resp_sb_tlv {
|
||||
__le16 reserved_16;
|
||||
};
|
||||
|
||||
/* cmdq_create_srq (size:384b/48B) */
|
||||
/* cmdq_create_srq (size:448b/56B) */
|
||||
struct cmdq_create_srq {
|
||||
u8 opcode;
|
||||
#define CMDQ_CREATE_SRQ_OPCODE_CREATE_SRQ 0x5UL
|
||||
#define CMDQ_CREATE_SRQ_OPCODE_LAST CMDQ_CREATE_SRQ_OPCODE_CREATE_SRQ
|
||||
u8 cmd_size;
|
||||
__le16 flags;
|
||||
#define CMDQ_CREATE_SRQ_FLAGS_STEERING_TAG_VALID 0x1UL
|
||||
__le16 cookie;
|
||||
u8 resp_size;
|
||||
u8 reserved8;
|
||||
@@ -1012,6 +1019,8 @@ struct cmdq_create_srq {
|
||||
__le32 dpi;
|
||||
__le32 pd_id;
|
||||
__le64 pbl;
|
||||
__le16 steering_tag;
|
||||
u8 reserved48[6];
|
||||
};
|
||||
|
||||
/* creq_create_srq_resp (size:128b/16B) */
|
||||
@@ -1118,7 +1127,7 @@ struct creq_query_srq_resp_sb {
|
||||
__le32 data[4];
|
||||
};
|
||||
|
||||
/* cmdq_create_cq (size:384b/48B) */
|
||||
/* cmdq_create_cq (size:448b/56B) */
|
||||
struct cmdq_create_cq {
|
||||
u8 opcode;
|
||||
#define CMDQ_CREATE_CQ_OPCODE_CREATE_CQ 0x9UL
|
||||
@@ -1126,6 +1135,8 @@ struct cmdq_create_cq {
|
||||
u8 cmd_size;
|
||||
__le16 flags;
|
||||
#define CMDQ_CREATE_CQ_FLAGS_DISABLE_CQ_OVERFLOW_DETECTION 0x1UL
|
||||
#define CMDQ_CREATE_CQ_FLAGS_STEERING_TAG_VALID 0x2UL
|
||||
#define CMDQ_CREATE_CQ_FLAGS_INFINITE_CQ_MODE 0x4UL
|
||||
__le16 cookie;
|
||||
u8 resp_size;
|
||||
u8 reserved8;
|
||||
@@ -1157,6 +1168,8 @@ struct cmdq_create_cq {
|
||||
__le32 dpi;
|
||||
__le32 cq_size;
|
||||
__le64 pbl;
|
||||
__le16 steering_tag;
|
||||
u8 reserved48[6];
|
||||
};
|
||||
|
||||
/* creq_create_cq_resp (size:128b/16B) */
|
||||
@@ -1288,11 +1301,12 @@ struct cmdq_allocate_mrw {
|
||||
#define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A 0x3UL
|
||||
#define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B 0x4UL
|
||||
#define CMDQ_ALLOCATE_MRW_MRW_FLAGS_LAST CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
|
||||
#define CMDQ_ALLOCATE_MRW_UNUSED4_MASK 0xf0UL
|
||||
#define CMDQ_ALLOCATE_MRW_UNUSED4_SFT 4
|
||||
#define CMDQ_ALLOCATE_MRW_STEERING_TAG_VALID 0x10UL
|
||||
#define CMDQ_ALLOCATE_MRW_UNUSED4_MASK 0xe0UL
|
||||
#define CMDQ_ALLOCATE_MRW_UNUSED4_SFT 5
|
||||
u8 access;
|
||||
#define CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY 0x20UL
|
||||
__le16 unused16;
|
||||
__le16 steering_tag;
|
||||
__le32 pd_id;
|
||||
};
|
||||
|
||||
@@ -1359,14 +1373,16 @@ struct creq_deallocate_key_resp {
|
||||
__le32 bound_window_info;
|
||||
};
|
||||
|
||||
/* cmdq_register_mr (size:384b/48B) */
|
||||
/* cmdq_register_mr (size:448b/56B) */
|
||||
struct cmdq_register_mr {
|
||||
u8 opcode;
|
||||
#define CMDQ_REGISTER_MR_OPCODE_REGISTER_MR 0xfUL
|
||||
#define CMDQ_REGISTER_MR_OPCODE_LAST CMDQ_REGISTER_MR_OPCODE_REGISTER_MR
|
||||
u8 cmd_size;
|
||||
__le16 flags;
|
||||
#define CMDQ_REGISTER_MR_FLAGS_ALLOC_MR 0x1UL
|
||||
#define CMDQ_REGISTER_MR_FLAGS_ALLOC_MR 0x1UL
|
||||
#define CMDQ_REGISTER_MR_FLAGS_STEERING_TAG_VALID 0x2UL
|
||||
#define CMDQ_REGISTER_MR_FLAGS_ENABLE_RO 0x4UL
|
||||
__le16 cookie;
|
||||
u8 resp_size;
|
||||
u8 reserved8;
|
||||
@@ -1415,6 +1431,8 @@ struct cmdq_register_mr {
|
||||
__le64 pbl;
|
||||
__le64 va;
|
||||
__le64 mr_size;
|
||||
__le16 steering_tag;
|
||||
u8 reserved48[6];
|
||||
};
|
||||
|
||||
/* creq_register_mr_resp (size:128b/16B) */
|
||||
|
||||
@@ -1222,6 +1222,8 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
int ret;
|
||||
|
||||
ep = lookup_atid(t, atid);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("ep %p tid %u snd_isn %u rcv_isn %u\n", ep, tid,
|
||||
be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn));
|
||||
@@ -2279,6 +2281,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
int ret = 0;
|
||||
|
||||
ep = lookup_atid(t, atid);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
|
||||
la = (struct sockaddr_in *)&ep->com.local_addr;
|
||||
ra = (struct sockaddr_in *)&ep->com.remote_addr;
|
||||
la6 = (struct sockaddr_in6 *)&ep->com.local_addr;
|
||||
|
||||
@@ -1126,13 +1126,19 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
|
||||
goto err_free_mm2;
|
||||
|
||||
mm->key = uresp.key;
|
||||
mm->addr = virt_to_phys(chp->cq.queue);
|
||||
mm->addr = 0;
|
||||
mm->vaddr = chp->cq.queue;
|
||||
mm->dma_addr = chp->cq.dma_addr;
|
||||
mm->len = chp->cq.memsize;
|
||||
insert_flag_to_mmap(&rhp->rdev, mm, mm->addr);
|
||||
insert_mmap(ucontext, mm);
|
||||
|
||||
mm2->key = uresp.gts_key;
|
||||
mm2->addr = chp->cq.bar2_pa;
|
||||
mm2->len = PAGE_SIZE;
|
||||
mm2->vaddr = NULL;
|
||||
mm2->dma_addr = 0;
|
||||
insert_flag_to_mmap(&rhp->rdev, mm2, mm2->addr);
|
||||
insert_mmap(ucontext, mm2);
|
||||
}
|
||||
|
||||
|
||||
@@ -532,11 +532,21 @@ static inline struct c4iw_ucontext *to_c4iw_ucontext(struct ib_ucontext *c)
|
||||
return container_of(c, struct c4iw_ucontext, ibucontext);
|
||||
}
|
||||
|
||||
enum {
|
||||
CXGB4_MMAP_BAR,
|
||||
CXGB4_MMAP_BAR_WC,
|
||||
CXGB4_MMAP_CONTIG,
|
||||
CXGB4_MMAP_NON_CONTIG,
|
||||
};
|
||||
|
||||
struct c4iw_mm_entry {
|
||||
struct list_head entry;
|
||||
u64 addr;
|
||||
u32 key;
|
||||
void *vaddr;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned len;
|
||||
u8 mmap_flag;
|
||||
};
|
||||
|
||||
static inline struct c4iw_mm_entry *remove_mmap(struct c4iw_ucontext *ucontext,
|
||||
@@ -561,6 +571,32 @@ static inline struct c4iw_mm_entry *remove_mmap(struct c4iw_ucontext *ucontext,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void insert_flag_to_mmap(struct c4iw_rdev *rdev,
|
||||
struct c4iw_mm_entry *mm, u64 addr)
|
||||
{
|
||||
if (addr >= pci_resource_start(rdev->lldi.pdev, 0) &&
|
||||
(addr < (pci_resource_start(rdev->lldi.pdev, 0) +
|
||||
pci_resource_len(rdev->lldi.pdev, 0))))
|
||||
mm->mmap_flag = CXGB4_MMAP_BAR;
|
||||
else if (addr >= pci_resource_start(rdev->lldi.pdev, 2) &&
|
||||
(addr < (pci_resource_start(rdev->lldi.pdev, 2) +
|
||||
pci_resource_len(rdev->lldi.pdev, 2)))) {
|
||||
if (addr >= rdev->oc_mw_pa) {
|
||||
mm->mmap_flag = CXGB4_MMAP_BAR_WC;
|
||||
} else {
|
||||
if (is_t4(rdev->lldi.adapter_type))
|
||||
mm->mmap_flag = CXGB4_MMAP_BAR;
|
||||
else
|
||||
mm->mmap_flag = CXGB4_MMAP_BAR_WC;
|
||||
}
|
||||
} else {
|
||||
if (addr)
|
||||
mm->mmap_flag = CXGB4_MMAP_CONTIG;
|
||||
else
|
||||
mm->mmap_flag = CXGB4_MMAP_NON_CONTIG;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void insert_mmap(struct c4iw_ucontext *ucontext,
|
||||
struct c4iw_mm_entry *mm)
|
||||
{
|
||||
@@ -936,7 +972,6 @@ u32 c4iw_get_resource(struct c4iw_id_table *id_table);
|
||||
void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry);
|
||||
int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt,
|
||||
u32 nr_pdid, u32 nr_srqt);
|
||||
int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev);
|
||||
int c4iw_pblpool_create(struct c4iw_rdev *rdev);
|
||||
int c4iw_rqtpool_create(struct c4iw_rdev *rdev);
|
||||
int c4iw_ocqp_pool_create(struct c4iw_rdev *rdev);
|
||||
@@ -944,7 +979,6 @@ void c4iw_pblpool_destroy(struct c4iw_rdev *rdev);
|
||||
void c4iw_rqtpool_destroy(struct c4iw_rdev *rdev);
|
||||
void c4iw_ocqp_pool_destroy(struct c4iw_rdev *rdev);
|
||||
void c4iw_destroy_resource(struct c4iw_resource *rscp);
|
||||
int c4iw_destroy_ctrl_qp(struct c4iw_rdev *rdev);
|
||||
void c4iw_register_device(struct work_struct *work);
|
||||
void c4iw_unregister_device(struct c4iw_dev *dev);
|
||||
int __init c4iw_cm_init(void);
|
||||
@@ -1006,8 +1040,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp);
|
||||
int c4iw_flush_rq(struct t4_wq *wq, struct t4_cq *cq, int count);
|
||||
int c4iw_flush_sq(struct c4iw_qp *qhp);
|
||||
int c4iw_ev_handler(struct c4iw_dev *rnicp, u32 qid);
|
||||
u16 c4iw_rqes_posted(struct c4iw_qp *qhp);
|
||||
int c4iw_post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe);
|
||||
u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx);
|
||||
void c4iw_put_cqid(struct c4iw_rdev *rdev, u32 qid,
|
||||
struct c4iw_dev_ucontext *uctx);
|
||||
|
||||
@@ -113,6 +113,9 @@ static int c4iw_alloc_ucontext(struct ib_ucontext *ucontext,
|
||||
mm->key = uresp.status_page_key;
|
||||
mm->addr = virt_to_phys(rhp->rdev.status_page);
|
||||
mm->len = PAGE_SIZE;
|
||||
mm->vaddr = NULL;
|
||||
mm->dma_addr = 0;
|
||||
insert_flag_to_mmap(&rhp->rdev, mm, mm->addr);
|
||||
insert_mmap(context, mm);
|
||||
}
|
||||
return 0;
|
||||
@@ -131,6 +134,11 @@ static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
|
||||
struct c4iw_mm_entry *mm;
|
||||
struct c4iw_ucontext *ucontext;
|
||||
u64 addr;
|
||||
u8 mmap_flag;
|
||||
size_t size;
|
||||
void *vaddr;
|
||||
unsigned long vm_pgoff;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
pr_debug("pgoff 0x%lx key 0x%x len %d\n", vma->vm_pgoff,
|
||||
key, len);
|
||||
@@ -145,47 +153,38 @@ static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
|
||||
if (!mm)
|
||||
return -EINVAL;
|
||||
addr = mm->addr;
|
||||
vaddr = mm->vaddr;
|
||||
dma_addr = mm->dma_addr;
|
||||
size = mm->len;
|
||||
mmap_flag = mm->mmap_flag;
|
||||
kfree(mm);
|
||||
|
||||
if ((addr >= pci_resource_start(rdev->lldi.pdev, 0)) &&
|
||||
(addr < (pci_resource_start(rdev->lldi.pdev, 0) +
|
||||
pci_resource_len(rdev->lldi.pdev, 0)))) {
|
||||
|
||||
/*
|
||||
* MA_SYNC register...
|
||||
*/
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
switch (mmap_flag) {
|
||||
case CXGB4_MMAP_BAR:
|
||||
ret = io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
|
||||
len,
|
||||
pgprot_noncached(vma->vm_page_prot));
|
||||
break;
|
||||
case CXGB4_MMAP_BAR_WC:
|
||||
ret = io_remap_pfn_range(vma, vma->vm_start,
|
||||
addr >> PAGE_SHIFT,
|
||||
len, t4_pgprot_wc(vma->vm_page_prot));
|
||||
break;
|
||||
case CXGB4_MMAP_CONTIG:
|
||||
ret = io_remap_pfn_range(vma, vma->vm_start,
|
||||
addr >> PAGE_SHIFT,
|
||||
len, vma->vm_page_prot);
|
||||
} else if ((addr >= pci_resource_start(rdev->lldi.pdev, 2)) &&
|
||||
(addr < (pci_resource_start(rdev->lldi.pdev, 2) +
|
||||
pci_resource_len(rdev->lldi.pdev, 2)))) {
|
||||
|
||||
/*
|
||||
* Map user DB or OCQP memory...
|
||||
*/
|
||||
if (addr >= rdev->oc_mw_pa)
|
||||
vma->vm_page_prot = t4_pgprot_wc(vma->vm_page_prot);
|
||||
else {
|
||||
if (!is_t4(rdev->lldi.adapter_type))
|
||||
vma->vm_page_prot =
|
||||
t4_pgprot_wc(vma->vm_page_prot);
|
||||
else
|
||||
vma->vm_page_prot =
|
||||
pgprot_noncached(vma->vm_page_prot);
|
||||
}
|
||||
ret = io_remap_pfn_range(vma, vma->vm_start,
|
||||
addr >> PAGE_SHIFT,
|
||||
len, vma->vm_page_prot);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Map WQ or CQ contig dma memory...
|
||||
*/
|
||||
ret = remap_pfn_range(vma, vma->vm_start,
|
||||
addr >> PAGE_SHIFT,
|
||||
len, vma->vm_page_prot);
|
||||
break;
|
||||
case CXGB4_MMAP_NON_CONTIG:
|
||||
vm_pgoff = vma->vm_pgoff;
|
||||
vma->vm_pgoff = 0;
|
||||
ret = dma_mmap_coherent(&rdev->lldi.pdev->dev, vma,
|
||||
vaddr, dma_addr, size);
|
||||
vma->vm_pgoff = vm_pgoff;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -2281,24 +2281,39 @@ int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
|
||||
if (ret)
|
||||
goto err_free_ma_sync_key;
|
||||
sq_key_mm->key = uresp.sq_key;
|
||||
sq_key_mm->addr = qhp->wq.sq.phys_addr;
|
||||
sq_key_mm->addr = 0;
|
||||
sq_key_mm->vaddr = qhp->wq.sq.queue;
|
||||
sq_key_mm->dma_addr = qhp->wq.sq.dma_addr;
|
||||
sq_key_mm->len = PAGE_ALIGN(qhp->wq.sq.memsize);
|
||||
insert_flag_to_mmap(&rhp->rdev, sq_key_mm, sq_key_mm->addr);
|
||||
insert_mmap(ucontext, sq_key_mm);
|
||||
if (!attrs->srq) {
|
||||
rq_key_mm->key = uresp.rq_key;
|
||||
rq_key_mm->addr = virt_to_phys(qhp->wq.rq.queue);
|
||||
rq_key_mm->addr = 0;
|
||||
rq_key_mm->vaddr = qhp->wq.rq.queue;
|
||||
rq_key_mm->dma_addr = qhp->wq.rq.dma_addr;
|
||||
rq_key_mm->len = PAGE_ALIGN(qhp->wq.rq.memsize);
|
||||
insert_flag_to_mmap(&rhp->rdev, rq_key_mm,
|
||||
rq_key_mm->addr);
|
||||
insert_mmap(ucontext, rq_key_mm);
|
||||
}
|
||||
sq_db_key_mm->key = uresp.sq_db_gts_key;
|
||||
sq_db_key_mm->addr = (u64)(unsigned long)qhp->wq.sq.bar2_pa;
|
||||
sq_db_key_mm->vaddr = NULL;
|
||||
sq_db_key_mm->dma_addr = 0;
|
||||
sq_db_key_mm->len = PAGE_SIZE;
|
||||
insert_flag_to_mmap(&rhp->rdev, sq_db_key_mm,
|
||||
sq_db_key_mm->addr);
|
||||
insert_mmap(ucontext, sq_db_key_mm);
|
||||
if (!attrs->srq) {
|
||||
rq_db_key_mm->key = uresp.rq_db_gts_key;
|
||||
rq_db_key_mm->addr =
|
||||
(u64)(unsigned long)qhp->wq.rq.bar2_pa;
|
||||
rq_db_key_mm->len = PAGE_SIZE;
|
||||
rq_db_key_mm->vaddr = NULL;
|
||||
rq_db_key_mm->dma_addr = 0;
|
||||
insert_flag_to_mmap(&rhp->rdev, rq_db_key_mm,
|
||||
rq_db_key_mm->addr);
|
||||
insert_mmap(ucontext, rq_db_key_mm);
|
||||
}
|
||||
if (ma_sync_key_mm) {
|
||||
@@ -2307,6 +2322,10 @@ int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
|
||||
(pci_resource_start(rhp->rdev.lldi.pdev, 0) +
|
||||
PCIE_MA_SYNC_A) & PAGE_MASK;
|
||||
ma_sync_key_mm->len = PAGE_SIZE;
|
||||
ma_sync_key_mm->vaddr = NULL;
|
||||
ma_sync_key_mm->dma_addr = 0;
|
||||
insert_flag_to_mmap(&rhp->rdev, ma_sync_key_mm,
|
||||
ma_sync_key_mm->addr);
|
||||
insert_mmap(ucontext, ma_sync_key_mm);
|
||||
}
|
||||
|
||||
@@ -2761,12 +2780,19 @@ int c4iw_create_srq(struct ib_srq *ib_srq, struct ib_srq_init_attr *attrs,
|
||||
if (ret)
|
||||
goto err_free_srq_db_key_mm;
|
||||
srq_key_mm->key = uresp.srq_key;
|
||||
srq_key_mm->addr = virt_to_phys(srq->wq.queue);
|
||||
srq_key_mm->addr = 0;
|
||||
srq_key_mm->len = PAGE_ALIGN(srq->wq.memsize);
|
||||
srq_key_mm->vaddr = srq->wq.queue;
|
||||
srq_key_mm->dma_addr = srq->wq.dma_addr;
|
||||
insert_flag_to_mmap(&rhp->rdev, srq_key_mm, srq_key_mm->addr);
|
||||
insert_mmap(ucontext, srq_key_mm);
|
||||
srq_db_key_mm->key = uresp.srq_db_gts_key;
|
||||
srq_db_key_mm->addr = (u64)(unsigned long)srq->wq.bar2_pa;
|
||||
srq_db_key_mm->len = PAGE_SIZE;
|
||||
srq_db_key_mm->vaddr = NULL;
|
||||
srq_db_key_mm->dma_addr = 0;
|
||||
insert_flag_to_mmap(&rhp->rdev, srq_db_key_mm,
|
||||
srq_db_key_mm->addr);
|
||||
insert_mmap(ucontext, srq_db_key_mm);
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length,
|
||||
struct ib_mr *efa_reg_user_mr_dmabuf(struct ib_pd *ibpd, u64 start,
|
||||
u64 length, u64 virt_addr,
|
||||
int fd, int access_flags,
|
||||
struct ib_udata *udata);
|
||||
struct uverbs_attr_bundle *attrs);
|
||||
int efa_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata);
|
||||
int efa_get_port_immutable(struct ib_device *ibdev, u32 port_num,
|
||||
struct ib_port_immutable *immutable);
|
||||
|
||||
@@ -674,6 +674,9 @@ struct efa_admin_feature_device_attr_desc {
|
||||
|
||||
/* Max RDMA transfer size in bytes */
|
||||
u32 max_rdma_size;
|
||||
|
||||
/* Unique global ID for an EFA device */
|
||||
u64 guid;
|
||||
};
|
||||
|
||||
struct efa_admin_feature_queue_attr_desc {
|
||||
|
||||
@@ -465,6 +465,7 @@ int efa_com_get_device_attr(struct efa_com_dev *edev,
|
||||
result->db_bar = resp.u.device_attr.db_bar;
|
||||
result->max_rdma_size = resp.u.device_attr.max_rdma_size;
|
||||
result->device_caps = resp.u.device_attr.device_caps;
|
||||
result->guid = resp.u.device_attr.guid;
|
||||
|
||||
if (result->admin_api_version < 1) {
|
||||
ibdev_err_ratelimited(
|
||||
|
||||
@@ -112,6 +112,7 @@ struct efa_com_get_device_attr_result {
|
||||
u8 addr[EFA_GID_SIZE];
|
||||
u64 page_size_cap;
|
||||
u64 max_mr_pages;
|
||||
u64 guid;
|
||||
u32 mtu;
|
||||
u32 fw_version;
|
||||
u32 admin_api_version;
|
||||
|
||||
@@ -441,6 +441,7 @@ static int efa_ib_device_add(struct efa_dev *dev)
|
||||
efa_set_host_info(dev);
|
||||
|
||||
dev->ibdev.node_type = RDMA_NODE_UNSPECIFIED;
|
||||
dev->ibdev.node_guid = dev->dev_attr.guid;
|
||||
dev->ibdev.phys_port_cnt = 1;
|
||||
dev->ibdev.num_comp_vectors = dev->neqs ?: 1;
|
||||
dev->ibdev.dev.parent = &pdev->dev;
|
||||
|
||||
@@ -1684,14 +1684,14 @@ static int efa_register_mr(struct ib_pd *ibpd, struct efa_mr *mr, u64 start,
|
||||
struct ib_mr *efa_reg_user_mr_dmabuf(struct ib_pd *ibpd, u64 start,
|
||||
u64 length, u64 virt_addr,
|
||||
int fd, int access_flags,
|
||||
struct ib_udata *udata)
|
||||
struct uverbs_attr_bundle *attrs)
|
||||
{
|
||||
struct efa_dev *dev = to_edev(ibpd->device);
|
||||
struct ib_umem_dmabuf *umem_dmabuf;
|
||||
struct efa_mr *mr;
|
||||
int err;
|
||||
|
||||
mr = efa_alloc_mr(ibpd, access_flags, udata);
|
||||
mr = efa_alloc_mr(ibpd, access_flags, &attrs->driver_udata);
|
||||
if (IS_ERR(mr)) {
|
||||
err = PTR_ERR(mr);
|
||||
goto err_out;
|
||||
|
||||
@@ -274,7 +274,8 @@ void notify_eq(struct erdma_eq *eq);
|
||||
void *get_next_valid_eqe(struct erdma_eq *eq);
|
||||
|
||||
int erdma_aeq_init(struct erdma_dev *dev);
|
||||
void erdma_aeq_destroy(struct erdma_dev *dev);
|
||||
int erdma_eq_common_init(struct erdma_dev *dev, struct erdma_eq *eq, u32 depth);
|
||||
void erdma_eq_destroy(struct erdma_dev *dev, struct erdma_eq *eq);
|
||||
|
||||
void erdma_aeq_event_handler(struct erdma_dev *dev);
|
||||
void erdma_ceq_completion_handler(struct erdma_eq_cb *ceq_cb);
|
||||
|
||||
@@ -158,20 +158,13 @@ static int erdma_cmdq_eq_init(struct erdma_dev *dev)
|
||||
{
|
||||
struct erdma_cmdq *cmdq = &dev->cmdq;
|
||||
struct erdma_eq *eq = &cmdq->eq;
|
||||
int ret;
|
||||
|
||||
eq->depth = cmdq->max_outstandings;
|
||||
eq->qbuf = dma_alloc_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT,
|
||||
&eq->qbuf_dma_addr, GFP_KERNEL);
|
||||
if (!eq->qbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&eq->lock);
|
||||
atomic64_set(&eq->event_num, 0);
|
||||
ret = erdma_eq_common_init(dev, eq, cmdq->max_outstandings);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
eq->db = dev->func_bar + ERDMA_REGS_CEQ_DB_BASE_REG;
|
||||
eq->dbrec = dma_pool_zalloc(dev->db_pool, GFP_KERNEL, &eq->dbrec_dma);
|
||||
if (!eq->dbrec)
|
||||
goto err_out;
|
||||
|
||||
erdma_reg_write32(dev, ERDMA_REGS_CMDQ_EQ_ADDR_H_REG,
|
||||
upper_32_bits(eq->qbuf_dma_addr));
|
||||
@@ -181,12 +174,6 @@ static int erdma_cmdq_eq_init(struct erdma_dev *dev)
|
||||
erdma_reg_write64(dev, ERDMA_CMDQ_EQ_DB_HOST_ADDR_REG, eq->dbrec_dma);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT, eq->qbuf,
|
||||
eq->qbuf_dma_addr);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int erdma_cmdq_init(struct erdma_dev *dev)
|
||||
@@ -247,10 +234,7 @@ void erdma_cmdq_destroy(struct erdma_dev *dev)
|
||||
|
||||
clear_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state);
|
||||
|
||||
dma_free_coherent(&dev->pdev->dev, cmdq->eq.depth << EQE_SHIFT,
|
||||
cmdq->eq.qbuf, cmdq->eq.qbuf_dma_addr);
|
||||
|
||||
dma_pool_free(dev->db_pool, cmdq->eq.dbrec, cmdq->eq.dbrec_dma);
|
||||
erdma_eq_destroy(dev, &cmdq->eq);
|
||||
|
||||
dma_free_coherent(&dev->pdev->dev, cmdq->sq.depth << SQEBB_SHIFT,
|
||||
cmdq->sq.qbuf, cmdq->sq.qbuf_dma_addr);
|
||||
|
||||
@@ -80,25 +80,51 @@ void erdma_aeq_event_handler(struct erdma_dev *dev)
|
||||
notify_eq(&dev->aeq);
|
||||
}
|
||||
|
||||
int erdma_aeq_init(struct erdma_dev *dev)
|
||||
int erdma_eq_common_init(struct erdma_dev *dev, struct erdma_eq *eq, u32 depth)
|
||||
{
|
||||
struct erdma_eq *eq = &dev->aeq;
|
||||
u32 buf_size = depth << EQE_SHIFT;
|
||||
|
||||
eq->depth = ERDMA_DEFAULT_EQ_DEPTH;
|
||||
|
||||
eq->qbuf = dma_alloc_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT,
|
||||
eq->qbuf = dma_alloc_coherent(&dev->pdev->dev, buf_size,
|
||||
&eq->qbuf_dma_addr, GFP_KERNEL);
|
||||
if (!eq->qbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
eq->dbrec = dma_pool_zalloc(dev->db_pool, GFP_KERNEL, &eq->dbrec_dma);
|
||||
if (!eq->dbrec)
|
||||
goto err_free_qbuf;
|
||||
|
||||
spin_lock_init(&eq->lock);
|
||||
atomic64_set(&eq->event_num, 0);
|
||||
atomic64_set(&eq->notify_num, 0);
|
||||
eq->ci = 0;
|
||||
eq->depth = depth;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_qbuf:
|
||||
dma_free_coherent(&dev->pdev->dev, buf_size, eq->qbuf,
|
||||
eq->qbuf_dma_addr);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void erdma_eq_destroy(struct erdma_dev *dev, struct erdma_eq *eq)
|
||||
{
|
||||
dma_pool_free(dev->db_pool, eq->dbrec, eq->dbrec_dma);
|
||||
dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT, eq->qbuf,
|
||||
eq->qbuf_dma_addr);
|
||||
}
|
||||
|
||||
int erdma_aeq_init(struct erdma_dev *dev)
|
||||
{
|
||||
struct erdma_eq *eq = &dev->aeq;
|
||||
int ret;
|
||||
|
||||
ret = erdma_eq_common_init(dev, &dev->aeq, ERDMA_DEFAULT_EQ_DEPTH);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
eq->db = dev->func_bar + ERDMA_REGS_AEQ_DB_REG;
|
||||
eq->dbrec = dma_pool_zalloc(dev->db_pool, GFP_KERNEL, &eq->dbrec_dma);
|
||||
if (!eq->dbrec)
|
||||
goto err_out;
|
||||
|
||||
erdma_reg_write32(dev, ERDMA_REGS_AEQ_ADDR_H_REG,
|
||||
upper_32_bits(eq->qbuf_dma_addr));
|
||||
@@ -108,22 +134,6 @@ int erdma_aeq_init(struct erdma_dev *dev)
|
||||
erdma_reg_write64(dev, ERDMA_AEQ_DB_HOST_ADDR_REG, eq->dbrec_dma);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT, eq->qbuf,
|
||||
eq->qbuf_dma_addr);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void erdma_aeq_destroy(struct erdma_dev *dev)
|
||||
{
|
||||
struct erdma_eq *eq = &dev->aeq;
|
||||
|
||||
dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT, eq->qbuf,
|
||||
eq->qbuf_dma_addr);
|
||||
|
||||
dma_pool_free(dev->db_pool, eq->dbrec, eq->dbrec_dma);
|
||||
}
|
||||
|
||||
void erdma_ceq_completion_handler(struct erdma_eq_cb *ceq_cb)
|
||||
@@ -234,32 +244,21 @@ static int erdma_ceq_init_one(struct erdma_dev *dev, u16 ceqn)
|
||||
struct erdma_eq *eq = &dev->ceqs[ceqn].eq;
|
||||
int ret;
|
||||
|
||||
eq->depth = ERDMA_DEFAULT_EQ_DEPTH;
|
||||
eq->qbuf = dma_alloc_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT,
|
||||
&eq->qbuf_dma_addr, GFP_KERNEL);
|
||||
if (!eq->qbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&eq->lock);
|
||||
atomic64_set(&eq->event_num, 0);
|
||||
atomic64_set(&eq->notify_num, 0);
|
||||
ret = erdma_eq_common_init(dev, eq, ERDMA_DEFAULT_EQ_DEPTH);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
eq->db = dev->func_bar + ERDMA_REGS_CEQ_DB_BASE_REG +
|
||||
(ceqn + 1) * ERDMA_DB_SIZE;
|
||||
|
||||
eq->dbrec = dma_pool_zalloc(dev->db_pool, GFP_KERNEL, &eq->dbrec_dma);
|
||||
if (!eq->dbrec) {
|
||||
dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT,
|
||||
eq->qbuf, eq->qbuf_dma_addr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
eq->ci = 0;
|
||||
dev->ceqs[ceqn].dev = dev;
|
||||
dev->ceqs[ceqn].ready = true;
|
||||
|
||||
/* CEQ indexed from 1, 0 rsvd for CMDQ-EQ. */
|
||||
ret = create_eq_cmd(dev, ceqn + 1, eq);
|
||||
dev->ceqs[ceqn].ready = ret ? false : true;
|
||||
if (ret) {
|
||||
erdma_eq_destroy(dev, eq);
|
||||
dev->ceqs[ceqn].ready = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -283,9 +282,7 @@ static void erdma_ceq_uninit_one(struct erdma_dev *dev, u16 ceqn)
|
||||
if (err)
|
||||
return;
|
||||
|
||||
dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT, eq->qbuf,
|
||||
eq->qbuf_dma_addr);
|
||||
dma_pool_free(dev->db_pool, eq->dbrec, eq->dbrec_dma);
|
||||
erdma_eq_destroy(dev, eq);
|
||||
}
|
||||
|
||||
int erdma_ceqs_init(struct erdma_dev *dev)
|
||||
|
||||
@@ -333,7 +333,7 @@ err_uninit_cmdq:
|
||||
erdma_cmdq_destroy(dev);
|
||||
|
||||
err_uninit_aeq:
|
||||
erdma_aeq_destroy(dev);
|
||||
erdma_eq_destroy(dev, &dev->aeq);
|
||||
|
||||
err_uninit_comm_irq:
|
||||
erdma_comm_irq_uninit(dev);
|
||||
@@ -366,7 +366,7 @@ static void erdma_remove_dev(struct pci_dev *pdev)
|
||||
erdma_ceqs_uninit(dev);
|
||||
erdma_hw_reset(dev);
|
||||
erdma_cmdq_destroy(dev);
|
||||
erdma_aeq_destroy(dev);
|
||||
erdma_eq_destroy(dev, &dev->aeq);
|
||||
erdma_comm_irq_uninit(dev);
|
||||
pci_free_irq_vectors(dev->pdev);
|
||||
erdma_device_uninit(dev);
|
||||
@@ -490,6 +490,7 @@ static const struct ib_device_ops erdma_device_ops = {
|
||||
.dereg_mr = erdma_dereg_mr,
|
||||
.destroy_cq = erdma_destroy_cq,
|
||||
.destroy_qp = erdma_destroy_qp,
|
||||
.disassociate_ucontext = erdma_disassociate_ucontext,
|
||||
.get_dma_mr = erdma_get_dma_mr,
|
||||
.get_hw_stats = erdma_get_hw_stats,
|
||||
.get_port_immutable = erdma_get_port_immutable,
|
||||
|
||||
@@ -1544,11 +1544,31 @@ int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum ib_qp_state query_qp_state(struct erdma_qp *qp)
|
||||
{
|
||||
switch (qp->attrs.state) {
|
||||
case ERDMA_QP_STATE_IDLE:
|
||||
return IB_QPS_INIT;
|
||||
case ERDMA_QP_STATE_RTR:
|
||||
return IB_QPS_RTR;
|
||||
case ERDMA_QP_STATE_RTS:
|
||||
return IB_QPS_RTS;
|
||||
case ERDMA_QP_STATE_CLOSING:
|
||||
return IB_QPS_ERR;
|
||||
case ERDMA_QP_STATE_TERMINATE:
|
||||
return IB_QPS_ERR;
|
||||
case ERDMA_QP_STATE_ERROR:
|
||||
return IB_QPS_ERR;
|
||||
default:
|
||||
return IB_QPS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
|
||||
{
|
||||
struct erdma_qp *qp;
|
||||
struct erdma_dev *dev;
|
||||
struct erdma_qp *qp;
|
||||
|
||||
if (ibqp && qp_attr && qp_init_attr) {
|
||||
qp = to_eqp(ibqp);
|
||||
@@ -1575,6 +1595,9 @@ int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
|
||||
qp_init_attr->cap = qp_attr->cap;
|
||||
|
||||
qp_attr->qp_state = query_qp_state(qp);
|
||||
qp_attr->cur_qp_state = query_qp_state(qp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1701,6 +1724,10 @@ err_out_xa:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void erdma_disassociate_ucontext(struct ib_ucontext *ibcontext)
|
||||
{
|
||||
}
|
||||
|
||||
void erdma_set_mtu(struct erdma_dev *dev, u32 mtu)
|
||||
{
|
||||
struct erdma_cmdq_config_mtu_req req;
|
||||
|
||||
@@ -344,6 +344,7 @@ int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
|
||||
struct ib_udata *data);
|
||||
int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
|
||||
int erdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
|
||||
void erdma_disassociate_ucontext(struct ib_ucontext *ibcontext);
|
||||
int erdma_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
|
||||
struct ib_mr *erdma_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
|
||||
u64 virt, int access, struct ib_udata *udata);
|
||||
|
||||
@@ -64,8 +64,10 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
|
||||
u8 tc_mode = 0;
|
||||
int ret;
|
||||
|
||||
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata)
|
||||
return -EOPNOTSUPP;
|
||||
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ah->av.port = rdma_ah_get_port_num(ah_attr);
|
||||
ah->av.gid_index = grh->sgid_index;
|
||||
@@ -83,7 +85,7 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
|
||||
ret = 0;
|
||||
|
||||
if (ret && grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
|
||||
return ret;
|
||||
goto err_out;
|
||||
|
||||
if (tc_mode == HNAE3_TC_MAP_MODE_DSCP &&
|
||||
grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
|
||||
@@ -91,8 +93,10 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
|
||||
else
|
||||
ah->av.sl = rdma_ah_get_sl(ah_attr);
|
||||
|
||||
if (!check_sl_valid(hr_dev, ah->av.sl))
|
||||
return -EINVAL;
|
||||
if (!check_sl_valid(hr_dev, ah->av.sl)) {
|
||||
ret = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE);
|
||||
memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
|
||||
|
||||
@@ -1041,9 +1041,9 @@ static bool hem_list_is_bottom_bt(int hopnum, int bt_level)
|
||||
* @bt_level: base address table level
|
||||
* @unit: ba entries per bt page
|
||||
*/
|
||||
static u32 hem_list_calc_ba_range(int hopnum, int bt_level, int unit)
|
||||
static u64 hem_list_calc_ba_range(int hopnum, int bt_level, int unit)
|
||||
{
|
||||
u32 step;
|
||||
u64 step;
|
||||
int max;
|
||||
int i;
|
||||
|
||||
@@ -1079,7 +1079,7 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,
|
||||
{
|
||||
struct hns_roce_buf_region *r;
|
||||
int total = 0;
|
||||
int step;
|
||||
u64 step;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < region_cnt; i++) {
|
||||
@@ -1110,7 +1110,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
|
||||
int ret = 0;
|
||||
int max_ofs;
|
||||
int level;
|
||||
u32 step;
|
||||
u64 step;
|
||||
int end;
|
||||
|
||||
if (hopnum <= 1)
|
||||
@@ -1134,10 +1134,12 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
|
||||
|
||||
/* config L1 bt to last bt and link them to corresponding parent */
|
||||
for (level = 1; level < hopnum; level++) {
|
||||
cur = hem_list_search_item(&mid_bt[level], offset);
|
||||
if (cur) {
|
||||
hem_ptrs[level] = cur;
|
||||
continue;
|
||||
if (!hem_list_is_bottom_bt(hopnum, level)) {
|
||||
cur = hem_list_search_item(&mid_bt[level], offset);
|
||||
if (cur) {
|
||||
hem_ptrs[level] = cur;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
step = hem_list_calc_ba_range(hopnum, level, unit);
|
||||
@@ -1147,7 +1149,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
|
||||
}
|
||||
|
||||
start_aligned = (distance / step) * step + r->offset;
|
||||
end = min_t(int, start_aligned + step - 1, max_ofs);
|
||||
end = min_t(u64, start_aligned + step - 1, max_ofs);
|
||||
cur = hem_list_alloc_item(hr_dev, start_aligned, end, unit,
|
||||
true);
|
||||
if (!cur) {
|
||||
@@ -1235,7 +1237,7 @@ static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
|
||||
struct hns_roce_hem_item *hem, *temp_hem;
|
||||
int total = 0;
|
||||
int offset;
|
||||
int step;
|
||||
u64 step;
|
||||
|
||||
step = hem_list_calc_ba_range(r->hopnum, 1, unit);
|
||||
if (step < 1)
|
||||
|
||||
@@ -1681,8 +1681,8 @@ static int hns_roce_hw_v2_query_counter(struct hns_roce_dev *hr_dev,
|
||||
|
||||
for (i = 0; i < HNS_ROCE_HW_CNT_TOTAL && i < *num_counters; i++) {
|
||||
bd_idx = i / CNT_PER_DESC;
|
||||
if (!(desc[bd_idx].flag & HNS_ROCE_CMD_FLAG_NEXT) &&
|
||||
bd_idx != HNS_ROCE_HW_CNT_TOTAL / CNT_PER_DESC)
|
||||
if (bd_idx != HNS_ROCE_HW_CNT_TOTAL / CNT_PER_DESC &&
|
||||
!(desc[bd_idx].flag & cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT)))
|
||||
break;
|
||||
|
||||
cnt_data = (__le64 *)&desc[bd_idx].data[0];
|
||||
@@ -2972,6 +2972,9 @@ err_llm_init_failed:
|
||||
|
||||
static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08)
|
||||
free_mr_exit(hr_dev);
|
||||
|
||||
hns_roce_function_clear(hr_dev);
|
||||
|
||||
if (!hr_dev->is_vf)
|
||||
@@ -4423,12 +4426,14 @@ static int config_qp_rq_buf(struct hns_roce_dev *hr_dev,
|
||||
upper_32_bits(to_hr_hw_page_addr(mtts[0])));
|
||||
hr_reg_clear(qpc_mask, QPC_RQ_CUR_BLK_ADDR_H);
|
||||
|
||||
context->rq_nxt_blk_addr = cpu_to_le32(to_hr_hw_page_addr(mtts[1]));
|
||||
qpc_mask->rq_nxt_blk_addr = 0;
|
||||
|
||||
hr_reg_write(context, QPC_RQ_NXT_BLK_ADDR_H,
|
||||
upper_32_bits(to_hr_hw_page_addr(mtts[1])));
|
||||
hr_reg_clear(qpc_mask, QPC_RQ_NXT_BLK_ADDR_H);
|
||||
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) {
|
||||
context->rq_nxt_blk_addr =
|
||||
cpu_to_le32(to_hr_hw_page_addr(mtts[1]));
|
||||
qpc_mask->rq_nxt_blk_addr = 0;
|
||||
hr_reg_write(context, QPC_RQ_NXT_BLK_ADDR_H,
|
||||
upper_32_bits(to_hr_hw_page_addr(mtts[1])));
|
||||
hr_reg_clear(qpc_mask, QPC_RQ_NXT_BLK_ADDR_H);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -6193,6 +6198,7 @@ static irqreturn_t abnormal_interrupt_basic(struct hns_roce_dev *hr_dev,
|
||||
struct pci_dev *pdev = hr_dev->pci_dev;
|
||||
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
|
||||
const struct hnae3_ae_ops *ops = ae_dev->ops;
|
||||
enum hnae3_reset_type reset_type;
|
||||
irqreturn_t int_work = IRQ_NONE;
|
||||
u32 int_en;
|
||||
|
||||
@@ -6204,10 +6210,12 @@ static irqreturn_t abnormal_interrupt_basic(struct hns_roce_dev *hr_dev,
|
||||
roce_write(hr_dev, ROCEE_VF_ABN_INT_ST_REG,
|
||||
1 << HNS_ROCE_V2_VF_INT_ST_AEQ_OVERFLOW_S);
|
||||
|
||||
reset_type = hr_dev->is_vf ?
|
||||
HNAE3_VF_FUNC_RESET : HNAE3_FUNC_RESET;
|
||||
|
||||
/* Set reset level for reset_event() */
|
||||
if (ops->set_default_reset_request)
|
||||
ops->set_default_reset_request(ae_dev,
|
||||
HNAE3_FUNC_RESET);
|
||||
ops->set_default_reset_request(ae_dev, reset_type);
|
||||
if (ops->reset_event)
|
||||
ops->reset_event(pdev, NULL);
|
||||
|
||||
@@ -6277,7 +6285,7 @@ static u64 fmea_get_ram_res_addr(u32 res_type, __le64 *data)
|
||||
res_type == ECC_RESOURCE_SCCC)
|
||||
return le64_to_cpu(*data);
|
||||
|
||||
return le64_to_cpu(*data) << PAGE_SHIFT;
|
||||
return le64_to_cpu(*data) << HNS_HW_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static int fmea_recover_others(struct hns_roce_dev *hr_dev, u32 res_type,
|
||||
@@ -6949,9 +6957,6 @@ static void __hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle,
|
||||
hr_dev->state = HNS_ROCE_DEVICE_STATE_UNINIT;
|
||||
hns_roce_handle_device_err(hr_dev);
|
||||
|
||||
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08)
|
||||
free_mr_exit(hr_dev);
|
||||
|
||||
hns_roce_exit(hr_dev);
|
||||
kfree(hr_dev->priv);
|
||||
ib_dealloc_device(&hr_dev->ib_dev);
|
||||
|
||||
@@ -1460,19 +1460,19 @@ void hns_roce_lock_cqs(struct hns_roce_cq *send_cq, struct hns_roce_cq *recv_cq)
|
||||
__acquire(&send_cq->lock);
|
||||
__acquire(&recv_cq->lock);
|
||||
} else if (unlikely(send_cq != NULL && recv_cq == NULL)) {
|
||||
spin_lock_irq(&send_cq->lock);
|
||||
spin_lock(&send_cq->lock);
|
||||
__acquire(&recv_cq->lock);
|
||||
} else if (unlikely(send_cq == NULL && recv_cq != NULL)) {
|
||||
spin_lock_irq(&recv_cq->lock);
|
||||
spin_lock(&recv_cq->lock);
|
||||
__acquire(&send_cq->lock);
|
||||
} else if (send_cq == recv_cq) {
|
||||
spin_lock_irq(&send_cq->lock);
|
||||
spin_lock(&send_cq->lock);
|
||||
__acquire(&recv_cq->lock);
|
||||
} else if (send_cq->cqn < recv_cq->cqn) {
|
||||
spin_lock_irq(&send_cq->lock);
|
||||
spin_lock(&send_cq->lock);
|
||||
spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
|
||||
} else {
|
||||
spin_lock_irq(&recv_cq->lock);
|
||||
spin_lock(&recv_cq->lock);
|
||||
spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
}
|
||||
@@ -1492,13 +1492,13 @@ void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq,
|
||||
spin_unlock(&recv_cq->lock);
|
||||
} else if (send_cq == recv_cq) {
|
||||
__release(&recv_cq->lock);
|
||||
spin_unlock_irq(&send_cq->lock);
|
||||
spin_unlock(&send_cq->lock);
|
||||
} else if (send_cq->cqn < recv_cq->cqn) {
|
||||
spin_unlock(&recv_cq->lock);
|
||||
spin_unlock_irq(&send_cq->lock);
|
||||
spin_unlock(&send_cq->lock);
|
||||
} else {
|
||||
spin_unlock(&send_cq->lock);
|
||||
spin_unlock_irq(&recv_cq->lock);
|
||||
spin_unlock(&recv_cq->lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1347,7 +1347,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
if (attr->max_dest_rd_atomic > dev->hw_attrs.max_hw_ird) {
|
||||
ibdev_err(&iwdev->ibdev,
|
||||
"rd_atomic = %d, above max_hw_ird=%d\n",
|
||||
attr->max_rd_atomic,
|
||||
attr->max_dest_rd_atomic,
|
||||
dev->hw_attrs.max_hw_ird);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3085,7 +3085,7 @@ error:
|
||||
static struct ib_mr *irdma_reg_user_mr_dmabuf(struct ib_pd *pd, u64 start,
|
||||
u64 len, u64 virt,
|
||||
int fd, int access,
|
||||
struct ib_udata *udata)
|
||||
struct uverbs_attr_bundle *attrs)
|
||||
{
|
||||
struct irdma_device *iwdev = to_iwdev(pd->device);
|
||||
struct ib_umem_dmabuf *umem_dmabuf;
|
||||
|
||||
@@ -383,7 +383,7 @@ static int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem
|
||||
|
||||
create_req->length = umem->length;
|
||||
create_req->offset_in_page = ib_umem_dma_offset(umem, page_sz);
|
||||
create_req->gdma_page_type = order_base_2(page_sz) - PAGE_SHIFT;
|
||||
create_req->gdma_page_type = order_base_2(page_sz) - MANA_PAGE_SHIFT;
|
||||
create_req->page_count = num_pages_total;
|
||||
|
||||
ibdev_dbg(&dev->ib_dev, "size_dma_region %lu num_pages_total %lu\n",
|
||||
@@ -511,13 +511,13 @@ int mana_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
|
||||
PAGE_SHIFT;
|
||||
prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
|
||||
ret = rdma_user_mmap_io(ibcontext, vma, pfn, gc->db_page_size, prot,
|
||||
ret = rdma_user_mmap_io(ibcontext, vma, pfn, PAGE_SIZE, prot,
|
||||
NULL);
|
||||
if (ret)
|
||||
ibdev_dbg(ibdev, "can't rdma_user_mmap_io ret %d\n", ret);
|
||||
else
|
||||
ibdev_dbg(ibdev, "mapped I/O pfn 0x%llx page_size %u, ret %d\n",
|
||||
pfn, gc->db_page_size, ret);
|
||||
ibdev_dbg(ibdev, "mapped I/O pfn 0x%llx page_size %lu, ret %d\n",
|
||||
pfn, PAGE_SIZE, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -829,7 +829,6 @@ void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
|
||||
|
||||
int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
|
||||
{
|
||||
char alias_wq_name[22];
|
||||
int ret = 0;
|
||||
int i, j;
|
||||
union ib_gid gid;
|
||||
@@ -875,9 +874,8 @@ int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
|
||||
dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
|
||||
dev->sriov.alias_guid.ports_guid[i].port = i;
|
||||
|
||||
snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
|
||||
dev->sriov.alias_guid.ports_guid[i].wq =
|
||||
alloc_ordered_workqueue(alias_wq_name, WQ_MEM_RECLAIM);
|
||||
alloc_ordered_workqueue("alias_guid%d", WQ_MEM_RECLAIM, i);
|
||||
if (!dev->sriov.alias_guid.ports_guid[i].wq) {
|
||||
ret = -ENOMEM;
|
||||
goto err_thread;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user