Kernel
Threads by month
- ----- 2026 -----
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- 31 participants
- 22402 discussions
[PATCH kernel-4.19 01/52] moduleparam: Save information about built-in modules in separate file
by Yang Yingliang 18 Mar '21
by Yang Yingliang 18 Mar '21
18 Mar '21
From: Alexey Gladkov <gladkov.alexey(a)gmail.com>
mainline inclusion
from mainline-v5.2-rc1
commit 898490c010b5d2e499e03b7e815fc214209ac583
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I390TB
CVE: NA
Backporting this patch is to fix an issue happened when the 5.10
kernel is building on openEuler 20.03 system.
In openEuler 20.03 system, some modules ware built-in kernel. But
in 5.10 kernel, those corresponding modules will be built as KO.
For built-in kernel, kmode 2.7+ will fetch the modinfo from
modules.builtin.modinfo which is only supported in kernel 5.2+.
In the rpmbuild process, kernel spec will call kmod to query
modinfo of the KO images. It will fail for 'file missing'.
With backporting the mainline commit below, kmod can fetch any module's
information from the corresponding module image or
modules.builtin.modinfo.
---------------------------
Problem:
When a kernel module is compiled as a separate module, some important
information about the kernel module is available via .modinfo section of
the module. In contrast, when the kernel module is compiled into the
kernel, that information is not available.
Information about built-in modules is necessary in the following cases:
1. When it is necessary to find out what additional parameters can be
passed to the kernel at boot time.
2. When you need to know which module names and their aliases are in
the kernel. This is very useful for creating an initrd image.
Proposal:
The proposed patch does not remove .modinfo section with module
information from the vmlinux at the build time and saves it into a
separate file after kernel linking. So, the kernel does not increase in
size and no additional information remains in it. Information is stored
in the same format as in the separate modules (null-terminated string
array). Because the .modinfo section is already exported with a separate
modules, we are not creating a new API.
It can be easily read in the userspace:
$ tr '\0' '\n' < modules.builtin.modinfo
ext4.softdep=pre: crc32c
ext4.license=GPL
ext4.description=Fourth Extended Filesystem
ext4.author=Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others
ext4.alias=fs-ext4
ext4.alias=ext3
ext4.alias=fs-ext3
ext4.alias=ext2
ext4.alias=fs-ext2
md_mod.alias=block-major-9-*
md_mod.alias=md
md_mod.description=MD RAID framework
md_mod.license=GPL
md_mod.parmtype=create_on_open:bool
md_mod.parmtype=start_dirty_degraded:int
...
Co-Developed-by: Gleb Fotengauer-Malinovskiy <glebfm(a)altlinux.org>
Signed-off-by: Gleb Fotengauer-Malinovskiy <glebfm(a)altlinux.org>
Signed-off-by: Alexey Gladkov <gladkov.alexey(a)gmail.com>
Acked-by: Jessica Yu <jeyu(a)kernel.org>
Signed-off-by: Masahiro Yamada <yamada.masahiro(a)socionext.com>
Signed-off-by: Zhichang Yuan <erik.yuan(a)arm.com>
Reviewed-by: Xie XiuQi <xiexiuqi(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
.gitignore | 1 +
Documentation/dontdiff | 1 +
Documentation/kbuild/kbuild.txt | 5 +++++
Makefile | 2 ++
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/module.h | 1 +
include/linux/moduleparam.h | 12 +++++-------
scripts/link-vmlinux.sh | 3 +++
8 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/.gitignore b/.gitignore
index 2d498af502ff1..546cef8d9b8fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ modules.builtin
/vmlinuz
/System.map
/Module.markers
+/modules.builtin.modinfo
#
# RPM spec file (make rpm-pkg)
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 2228fcc8e29f4..3d4d5a402b8be 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -179,6 +179,7 @@ mktables
mktree
modpost
modules.builtin
+modules.builtin.modinfo
modules.order
modversions.h*
nconf
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
index 8390c360d4b35..7f48e48f3fd27 100644
--- a/Documentation/kbuild/kbuild.txt
+++ b/Documentation/kbuild/kbuild.txt
@@ -11,6 +11,11 @@ modules.builtin
This file lists all modules that are built into the kernel. This is used
by modprobe to not fail when trying to load something builtin.
+modules.builtin.modinfo
+--------------------------------------------------
+This file contains modinfo from all modules that are built into the kernel.
+Unlike modinfo of a separate module, all fields are prefixed with module name.
+
Environment variables
diff --git a/Makefile b/Makefile
index 040b3cd699b01..e01e33b35daaf 100644
--- a/Makefile
+++ b/Makefile
@@ -1288,6 +1288,7 @@ _modinst_:
fi
@cp -f $(objtree)/modules.order $(MODLIB)/
@cp -f $(objtree)/modules.builtin $(MODLIB)/
+ @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
# This depmod is only for convenience to give the initial
@@ -1328,6 +1329,7 @@ endif # CONFIG_MODULES
# Directories & files removed with 'make clean'
CLEAN_DIRS += $(MODVERDIR) include/ksym
+CLEAN_FILES += modules.builtin.modinfo
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config usr/include include/generated \
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 2d632a74cc5e9..0276b6950ae1d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -855,6 +855,7 @@
EXIT_CALL \
*(.discard) \
*(.discard.*) \
+ *(.modinfo) \
}
/**
diff --git a/include/linux/module.h b/include/linux/module.h
index 49942432f0101..5056a346f69e9 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -239,6 +239,7 @@ extern typeof(name) __mod_##type##__##name##_device_table \
#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
#else
#define MODULE_VERSION(_version) \
+ MODULE_INFO(version, _version); \
static struct module_version_attribute ___modver_attr = { \
.mattr = { \
.attr = { \
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index ba36506db4fb7..5ba250d9172ac 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -10,23 +10,21 @@
module name. */
#ifdef MODULE
#define MODULE_PARAM_PREFIX /* empty */
+#define __MODULE_INFO_PREFIX /* empty */
#else
#define MODULE_PARAM_PREFIX KBUILD_MODNAME "."
+/* We cannot use MODULE_PARAM_PREFIX because some modules override it. */
+#define __MODULE_INFO_PREFIX KBUILD_MODNAME "."
#endif
/* Chosen so that structs with an unsigned long line up. */
#define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))
-#ifdef MODULE
#define __MODULE_INFO(tag, name, info) \
static const char __UNIQUE_ID(name)[] \
__used __attribute__((section(".modinfo"), unused, aligned(1))) \
- = __stringify(tag) "=" info
-#else /* !MODULE */
-/* This struct is here for syntactic coherency, it is not used */
-#define __MODULE_INFO(tag, name, info) \
- struct __UNIQUE_ID(name) {}
-#endif
+ = __MODULE_INFO_PREFIX __stringify(tag) "=" info
+
#define __MODULE_PARM_TYPE(name, _type) \
__MODULE_INFO(parmtype, name##type, #name ":" _type)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index c8cf45362bd6f..c09e87e9c2b9f 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -226,6 +226,9 @@ modpost_link vmlinux.o
# modpost vmlinux.o to check for section mismatches
${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
+info MODINFO modules.builtin.modinfo
+${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
+
kallsymso=""
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then
--
2.25.1
1
51
*** BLURB HERE ***
Andrew Murray (1):
arm64: Use correct ll/sc atomic constraints
Ard Biesheuvel (1):
crypto: tcrypt - avoid signed overflow in byte count
Chao Yu (1):
f2fs: fix to set/clear I_LINKABLE under i_lock
Chris Leech (2):
scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
scsi: iscsi: Verify lengths on passthrough PDUs
Christian Gromm (1):
staging: most: sound: add sanity check for function argument
Claire Chang (1):
Bluetooth: hci_h5: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for btrtl
Cornelia Huck (1):
virtio/s390: implement virtio-ccw revision 2 correctly
Di Zhu (1):
pktgen: fix misuse of BUG_ON() in pktgen_thread_worker()
Dinghao Liu (1):
staging: fwserial: Fix error handling in fwserial_create
Eckhart Mohr (1):
ALSA: hda/realtek: Add quirk for Clevo NH55RZQ
Fangrui Song (1):
x86/build: Treat R_386_PLT32 relocation as R_386_PC32
Geert Uytterhoeven (1):
dt-bindings: net: btusb: DT fix s/interrupt-name/interrupt-names/
Gopal Tiwari (1):
Bluetooth: Fix null pointer dereference in
amp_read_loc_assoc_final_data
Greg Kroah-Hartman (1):
Linux 4.19.179
Hans de Goede (3):
ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R
tablet
ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet
ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet
Heiner Kallweit (1):
x86/reboot: Add Zotac ZBOX CI327 nano PCI reboot quirk
Jaegeuk Kim (1):
f2fs: handle unallocated section and zone on pinned/atgc
Jan Beulich (2):
Xen/gnttab: handle p2m update errors on a per-slot basis
xen-netback: respect gnttab_map_refs()'s return value
Jens Axboe (1):
swap: fix swapfile read/write offset
Jiri Slaby (1):
vt/consolemap: do font sum unsigned
Joe Perches (1):
sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
John David Anglin (1):
parisc: Bump 64-bit IRQ stack size to 64 KB
Josef Bacik (1):
btrfs: fix error handling in commit_fs_roots
Lech Perczak (1):
net: usb: qmi_wwan: support ZTE P685M modem
Lee Duncan (1):
scsi: iscsi: Restrict sessions and handles to admin capabilities
Li Xinhai (1):
mm/hugetlb.c: fix unnecessary address expansion of pmd sharing
Marco Elver (1):
net: fix up truesize of cloned skb in skb_prepare_for_shift()
Marek Vasut (2):
rsi: Fix TX EAPOL packet handling against iwlwifi AP
rsi: Move card interrupt handling to RX thread
Miaoqing Pan (1):
ath10k: fix wmi mgmt tx queue full due to race condition
Mike Kravetz (1):
hugetlb: fix update_and_free_page contig page struct assumption
Nathan Chancellor (1):
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Nicholas Kazlauskas (1):
drm/amd/display: Guard against NULL pointer deref when get_i2c_info
fails
Nirmoy Das (1):
PCI: Add a REBAR size quirk for Sapphire RX 5600 XT Pulse
Randy Dunlap (1):
JFS: more checks for invalid superblock
Ricardo Ribalda (1):
media: uvcvideo: Allow entities with no pads
Rokudo Yan (1):
zsmalloc: account the number of compacted pages correctly
Sabyrzhan Tasbolatov (1):
smackfs: restrict bytes count in smackfs write functions
Sakari Ailus (1):
media: v4l: ioctl: Fix memory leak in video_usercopy
Sean Young (1):
media: mceusb: sanity check for prescaler value
Sergey Senozhatsky (1):
drm/virtio: use kvmalloc for large allocations
Shaoying Xu (1):
arm64 module: set plt* section addresses to 0x0
Takashi Iwai (1):
ALSA: hda/realtek: Apply dual codec quirks for MSI Godlike X570 board
Tony Lindgren (1):
wlcore: Fix command execute failure 19 for wl12xx
Vladimir Oltean (1):
net: bridge: use switchdev for port flags set through sysfs too
Will Deacon (2):
arm64: Avoid redundant type conversions in xchg() and cmpxchg()
arm64: cmpxchg: Use "K" instead of "L" for ll/sc immediate constraint
Yumei Huang (1):
xfs: Fix assert failure in xfs_setattr_size()
Zqiang (1):
udlfb: Fix memory leak in dlfb_usb_probe
.../devicetree/bindings/net/btusb.txt | 2 +-
Documentation/filesystems/sysfs.txt | 8 +-
Makefile | 2 +-
arch/arm/xen/p2m.c | 35 ++++-
arch/arm64/include/asm/atomic_ll_sc.h | 108 +++++++------
arch/arm64/include/asm/atomic_lse.h | 46 +++---
arch/arm64/include/asm/cmpxchg.h | 116 +++++++-------
arch/arm64/kernel/module.lds | 6 +-
arch/mips/vdso/Makefile | 5 +-
arch/parisc/kernel/irq.c | 4 +
arch/x86/kernel/module.c | 1 +
arch/x86/kernel/reboot.c | 9 ++
arch/x86/tools/relocs.c | 12 +-
arch/x86/xen/p2m.c | 44 +++++-
crypto/tcrypt.c | 20 +--
drivers/block/zram/zram_drv.c | 2 +-
drivers/bluetooth/hci_h5.c | 5 +
drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 +
drivers/gpu/drm/virtio/virtgpu_vq.c | 6 +-
drivers/media/rc/mceusb.c | 9 +-
drivers/media/usb/uvc/uvc_driver.c | 7 +-
drivers/media/v4l2-core/v4l2-ioctl.c | 19 +--
drivers/net/usb/qmi_wwan.c | 1 +
drivers/net/wireless/ath/ath10k/mac.c | 15 +-
drivers/net/wireless/rsi/rsi_91x_hal.c | 3 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 6 +-
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 52 ++----
drivers/net/wireless/rsi/rsi_sdio.h | 8 +-
drivers/net/wireless/ti/wl12xx/main.c | 3 -
drivers/net/wireless/ti/wlcore/main.c | 15 +-
drivers/net/wireless/ti/wlcore/wlcore.h | 3 -
drivers/net/xen-netback/netback.c | 12 +-
drivers/pci/pci.c | 9 +-
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/libiscsi.c | 148 +++++++++---------
drivers/scsi/scsi_transport_iscsi.c | 38 ++++-
drivers/staging/fwserial/fwserial.c | 2 +
drivers/staging/most/sound/sound.c | 2 +
drivers/tty/vt/consolemap.c | 2 +-
drivers/video/fbdev/udlfb.c | 1 +
fs/btrfs/transaction.c | 11 +-
fs/f2fs/namei.c | 8 +
fs/f2fs/segment.h | 4 +-
fs/jfs/jfs_filsys.h | 1 +
fs/jfs/jfs_mount.c | 10 ++
fs/sysfs/file.c | 55 +++++++
fs/xfs/xfs_iops.c | 2 +-
include/linux/sysfs.h | 16 ++
include/linux/zsmalloc.h | 2 +-
mm/hugetlb.c | 28 ++--
mm/page_io.c | 11 +-
mm/swapfile.c | 2 +-
mm/zsmalloc.c | 17 +-
net/bluetooth/amp.c | 3 +
net/bridge/br_sysfs_if.c | 9 +-
net/core/pktgen.c | 2 +-
net/core/skbuff.c | 14 +-
security/smack/smackfs.c | 21 ++-
sound/pci/hda/patch_realtek.c | 2 +
sound/soc/intel/boards/bytcr_rt5640.c | 37 +++++
60 files changed, 651 insertions(+), 399 deletions(-)
--
2.25.1
1
53
Adrian Hunter (1):
perf intel-pt: Fix missing CYC processing in PSB
Al Viro (1):
sparc32: fix a user-triggerable oops in clear_user()
Alain Volmat (1):
spi: stm32: properly handle 0 byte transfer
Alexander Lobakin (1):
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Alexander Usyskin (1):
watchdog: mei_wdt: request stop on unregister
Amey Narkhede (1):
staging: gdm724x: Fix DMA from stack
Andre Przywara (5):
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
clk: sunxi-ng: h6: Fix CEC clock
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Andrea Parri (Microsoft) (1):
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Andrii Nakryiko (1):
bpf: Avoid warning when re-casting __bpf_call_base into
__bpf_call_base_args
Andy Shevchenko (1):
spi: pxa2xx: Fix the controller numbering for Wildcat Point
AngeloGioacchino Del Regno (1):
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Ansuel Smith (1):
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ard Biesheuvel (1):
crypto: arm64/sha - add missing module aliases
Arnaldo Carvalho de Melo (1):
perf tools: Fix DSO filtering when not finding a map for a sampled
address
Arnd Bergmann (1):
ARM: s3c: fix fiq for clang IAS
Aswath Govindraju (2):
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
misc: eeprom_93xx46: Add module alias to avoid breaking support for
non device tree users
Ayush Sawal (1):
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in
cxgb4 and ulds
Bard Liao (1):
regmap: sdw: use _no_pm functions in regmap_read/write
Bartosz Golaszewski (1):
rtc: s5m: select REGMAP_I2C
Bob Pearson (2):
RDMA/rxe: Fix coding error in rxe_recv.c
RDMA/rxe: Correct skb on loopback path
Bob Peterson (1):
gfs2: Don't skip dlm unlock if glock has an lvb
Chao Yu (1):
f2fs: fix out-of-repair __setattr_copy()
Chen Yu (1):
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES
if available
Chen-Yu Tsai (1):
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory
rules
Chenyang Li (1):
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if
condition
Christoph Schemmel (1):
NET: usb: qmi_wwan: Adding support for Cinterion MV31
Christophe JAILLET (9):
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in
the probe function
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
media: vsp1: Fix an error handling path in the probe function
media: cx25821: Fix a bug when reallocating some dma memory
dmaengine: fsldma: Fix a resource leak in the remove function
dmaengine: fsldma: Fix a resource leak in an error handling path of
the probe function
dmaengine: owl-dma: Fix a resource leak in the remove function
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the
probe
Christophe Leroy (3):
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size
error)
powerpc/47x: Disable 256k page size
powerpc/8xx: Fix software emulation interrupt
Christopher William Snowhill (1):
Bluetooth: Fix initializing response id after clearing struct
Chuhong Yuan (1):
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Claudiu Beznea (1):
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Colin Ian King (3):
mac80211: fix potential overflow when multiplying to u32 integers
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
fs/jfs: fix potential integer overflow on shift of a int
Corentin Labbe (3):
crypto: sun4i-ss - fix kmap usage
crypto: sun4i-ss - checking sg length is not sufficient
crypto: sun4i-ss - handle BigEndian for cipher
Cédric Le Goater (1):
KVM: PPC: Make the VMX instruction emulation routines static
Dan Carpenter (11):
gma500: clean up error handling in init
media: camss: missing error code in msm_video_register()
ASoC: cs42l56: fix up error handling in probe
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Input: sur40 - fix an error code in sur40_probe()
Input: elo - fix an error code in elo_connect()
ocfs2: fix a use after free on error
Input: joydev - prevent potential read overflow in ioctl
USB: serial: mos7840: fix error code in mos7840_write()
USB: serial: mos7720: fix error code in mos7720_write()
Dan Williams (1):
libnvdimm/dimm: Avoid race between probe and available_slots_show()
Daniele Alessandrelli (1):
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
David Howells (1):
certs: Fix blacklist flag type confusion
Dinghao Liu (3):
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
media: media/pci: Fix memleak in empress_init
media: tm6000: Fix memleak in tm6000_start_stream
Edwin Peer (1):
bnxt_en: reverse order of TX disable and carrier off
Eric Biggers (1):
random: fix the RNDRESEEDCRNG ioctl
Eric Dumazet (2):
tcp: fix SO_RCVLOWAT related hangs under mem pressure
ipv6: icmp6: avoid indirect call for icmpv6_send()
Eric W. Biederman (1):
capabilities: Don't allow writing ambiguous v3 file capabilities
Fangrui Song (1):
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined
symbols
Ferry Toth (1):
dmaengine: hsu: disable spurious interrupt
Filipe Manana (1):
btrfs: fix extent buffer leak on failure to copy root
Florian Fainelli (1):
ata: ahci_brcm: Add back regulators management
Frank Li (1):
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Frank Wunderlich (1):
dts64: mt7622: fix slow sd card access
Geert Uytterhoeven (1):
auxdisplay: ht16k33: Fix refresh rate handling
Greg Kroah-Hartman (1):
Linux 4.19.178
Guenter Roeck (3):
usb: dwc2: Do not update data length if it is 0 on inbound transfers
usb: dwc2: Abort transaction after errors with unknown reason
usb: dwc2: Make "trimming xfer length" a debug message
He Zhe (1):
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
Heiner Kallweit (2):
PCI: Align checking of syscall user config accessors
r8169: fix jumbo packet handling on RTL8168e
Ilya Lipnitskiy (1):
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Jack Pham (1):
usb: gadget: u_audio: Free requests only after callback
Jacopo Mondi (1):
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Jae Hyun Yoo (1):
soc: aspeed: snoop: Add clock control logic
James Bottomley (2):
tpm_tis: Fix check_locality for correct locality acquisition
tpm_tis: Clean up locality release
Jan Henrik Weinstock (1):
hwrng: timeriomem - Fix cooldown period calculation
Jan Kara (2):
bfq: Avoid false bfq queue merging
quota: Fix memory leak when handling corrupted quota file
Jarkko Sakkinen (1):
KEYS: trusted: Fix migratable=1 failing
Jason A. Donenfeld (6):
icmp: introduce helper for nat'd source address in network device
context
icmp: allow icmpv6_ndo_send to work with CONFIG_IPV6=n
gtp: use icmp_ndo_send helper
sunvnet: use icmp_ndo_send helper
xfrm: interface: use icmp_ndo_send helper
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Jason Gerecke (1):
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Jesper Dangaard Brouer (1):
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jialin Zhang (1):
drm/gma500: Fix error return code in psb_driver_load()
Jiri Bohac (1):
pstore: Fix typo in compression option name
Jiri Kosina (1):
floppy: reintroduce O_NDELAY fix
Jiri Olsa (1):
crypto: bcm - Rename struct device_private to bcm_device_private
Joe Perches (1):
media: lmedm04: Fix misuse of comma
Johan Hovold (2):
USB: quirks: sort quirk entries
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
John Wang (1):
ARM: dts: aspeed: Add LCLK to lpc-snoop
Jorgen Hansen (1):
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Josef Bacik (2):
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Juergen Gross (1):
xen/netback: fix spurious event detection for common event case
KarimAllah Ahmed (1):
fdt: Properly handle "no-map" field in the memory region
Konrad Dybcio (1):
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Krzysztof Kozlowski (9):
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3
family
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
regulator: s5m8767: Drop regulators OF node reference
Lakshmi Ramasubramanian (2):
ima: Free IMA measurement buffer on error
ima: Free IMA measurement buffer after kexec syscall
Laurent Pinchart (1):
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Lech Perczak (1):
USB: serial: option: update interface mapping for ZTE P685M
Leon Romanovsky (1):
ipv6: silence compilation warning for non-IPV6 builds
Lijun Pan (2):
ibmvnic: add memory barrier to protect long term buffer
ibmvnic: skip send_request_unmap for timeout reset
Linus Lüssing (1):
ath9k: fix data bus crash when setting nf_override via debugfs
Luo Meng (1):
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Marc Zyngier (1):
arm64: Add missing ISB after invalidating TLB in __primary_switch
Marco Elver (1):
bpf_lru_list: Read double-checked variable once without lock
Marcos Paulo de Souza (1):
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Mario Kleiner (1):
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth
reduction.
Martin Blumenstingl (1):
clk: meson: clk-pll: fix initializing the old rate (fallback) for a
PLL
Martin Kaiser (1):
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Mateusz Palczewski (3):
i40e: Add zero-initialization of AQ command structures
i40e: Fix overwriting flow control settings during driver loading
i40e: Fix add TC filter for IPv6
Maxim Kiselev (1):
gpio: pcf857x: Fix missing first interrupt
Maxime Chevallier (1):
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Maxime Ripard (1):
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Maximilian Luz (1):
ACPICA: Fix exception code class checks
Miaohe Lin (3):
mm/memory.c: fix potential pte_unmap_unlock pte error
mm/hugetlb: fix potential double free in hugetlb_register_node() error
path
mm/rmap: fix potential pte_unmap on an not mapped pte
Mike Kravetz (1):
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mikulas Patocka (2):
blk-settings: align max_sectors on "logical_block_size" boundary
dm: fix deadlock when swapping to encrypted device
Muchun Song (1):
printk: fix deadlock when kernel panic
Namhyung Kim (1):
perf test: Fix unaligned access in sample parsing test
Nathan Chancellor (2):
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Lynch (1):
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
NeilBrown (2):
seq_file: document how per-entry resources are managed.
x86: fix seq_file iteration for pat/memtype.c
Nick Desaulniers (1):
vmlinux.lds.h: add DWARF v5 sections
Nicolas Boichat (1):
of/fdt: Make sure no-map does not remove already reserved regions
Nikos Tsironis (7):
dm era: Recover committed writeset after crash
dm era: Verify the data block size hasn't changed
dm era: Fix bitset memory leaks
dm era: Use correct value size in equality function of writeset tree
dm era: Reinitialize bitset cache before digesting a new writeset
dm era: only resize metadata in preresume
dm era: Update in-core bitset after committing the metadata
Olivier Crête (1):
Input: xpad - add support for PowerA Enhanced Wired Controller for
Xbox Series X|S
Pan Bian (8):
Bluetooth: drop HCI device reference before return
Bluetooth: Put HCI device if inquiry procedure interrupts
memory: ti-aemif: Drop child node when jumping out loop
regulator: axp20x: Fix reference cout leak
spi: atmel: Put allocated master before return
isofs: release buffer head before return
mtd: spi-nor: hisi-sfc: Put child node np on error path
fs/affs: release old buffer head on error path
Paul Cercueil (2):
usb: musb: Fix runtime PM race in musb_queue_resume_work
seccomp: Add missing return in non-void function
Pavel Machek (1):
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
PeiSen Hou (1):
ALSA: hda/realtek: modify EAPD in the ALC886
Peter Zijlstra (2):
jump_label/lockdep: Assert we hold the hotplug lock for _cpuslocked()
operations
locking/static_key: Fix false positive warnings on concurrent dec/inc
Pratyush Yadav (1):
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Qinglang Miao (1):
ACPI: configfs: add missing check after
configfs_register_default_group()
Rafael J. Wysocki (1):
ACPI: property: Fix fwnode string properties matching
Rakesh Pillai (1):
ath10k: Fix error handling in case of CE pipe init failure
Randy Dunlap (4):
fbdev: aty: SPARC64 requires FB_ATY_CT
HID: core: detect and skip invalid inputs to snto32()
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Ricky Wu (1):
misc: rtsx: init of rts522a add OCP power off when no card is present
Rolf Eike Beer (2):
scripts: use pkg-config to locate libcrypto
scripts: set proper OpenSSL include dir also for sign-file
Rong Chen (1):
scripts/recordmcount.pl: support big endian for ARCH sh
Rosen Penev (2):
ARM: dts: armada388-helios4: assign pinctrl to LEDs
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rustam Kovhaev (1):
ntfs: check for valid standard information attribute
Sabyrzhan Tasbolatov (1):
drivers/misc/vmw_vmci: restrict too big queue size in
qp_host_alloc_queue
Sameer Pujar (1):
arm64: tegra: Add power-domain for Tegra210 HDA
Sean Christopherson (1):
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sebastian Reichel (1):
ASoC: cpcap: fix microphone timeslot mask
Shay Drory (2):
IB/umad: Return EIO in case of when device disassociated
IB/umad: Return EPOLLERR in case of when device disassociated
Shyam Prasad N (1):
cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting cifs_sb->prepath.
Shyam Sundar S K (4):
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
net: amd-xgbe: Reset link when the link never comes back
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Simon South (1):
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous
clk_unprepare()
Slawomir Laba (1):
i40e: Fix flow for IPv6 next header (extension header)
Stefan Ursella (1):
usb: quirks: add quirk to start video capture on ELMO L-12F document
camera reliable
Steven Rostedt (VMware) (1):
tracepoint: Do not fail unregistering a probe due to memory failure
Sukadev Bhattiprolu (1):
ibmvnic: Set to CLOSED state even on error
Sumit Garg (1):
kdb: Make memory allocations more robust
Suzuki K Poulose (1):
arm64: Extend workaround for erratum 1024718 to all versions of
Cortex-A55
Sylwester Dziedziuch (1):
i40e: Fix VFs not created
Taehee Yoo (1):
vxlan: move debug check after netdev unregister
Takashi Iwai (1):
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Takeshi Misawa (1):
net: qrtr: Fix memory leak in qrtr_tun_open
Takeshi Saito (1):
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to
128-bytes
Theodore Ts'o (1):
ext4: fix potential htree index checksum corruption
Thinh Nguyen (2):
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Tom Rix (3):
media: pxa_camera: declare variable when DEBUG is defined
jffs2: fix use after free in jffs2_sum_write_data()
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is
defined
Tony Lindgren (1):
ARM: dts: Configure missing thermal interrupt for 4430
Uwe Kleine-König (1):
amba: Fix resource leak for drivers without .remove
Vincent Knecht (1):
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Vladimir Murzin (1):
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Will McVicker (1):
HID: make arrays usage and value to be the same
Yi Chen (1):
f2fs: fix to avoid inconsistent quota data
Yishai Hadas (1):
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Yoshihiro Shimoda (1):
mfd: bd9571mwv: Use devm_mfd_add_devices()
Zhihao Cheng (1):
btrfs: clarify error returns values in __load_free_space_cache
jeffrey.lin (1):
Input: raydium_ts_i2c - do not send zero length
Documentation/filesystems/seq_file.txt | 6 +
Makefile | 2 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +++-
arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
arch/arm/boot/dts/exynos3250-artik5.dtsi | 2 +-
arch/arm/boot/dts/exynos3250-monk.dts | 2 +-
arch/arm/boot/dts/exynos3250-rinato.dts | 2 +-
arch/arm/boot/dts/exynos5250-spring.dts | 2 +-
arch/arm/boot/dts/exynos5420-arndale-octa.dts | 2 +-
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 2 +-
arch/arm/boot/dts/omap443x.dtsi | 2 +
arch/arm64/Kconfig | 2 +-
.../dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
.../dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
.../boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 1 +
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/crypto/sha1-ce-glue.c | 1 +
arch/arm64/crypto/sha2-ce-glue.c | 2 +
arch/arm64/crypto/sha3-ce-glue.c | 4 +
arch/arm64/crypto/sha512-ce-glue.c | 2 +
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/mips/kernel/vmlinux.lds.S | 1 +
arch/mips/lantiq/irq.c | 2 +-
arch/mips/mm/c-r4k.c | 2 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/lib/memset.S | 1 +
arch/x86/kernel/reboot.c | 29 ++--
arch/x86/mm/pat.c | 3 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 ++
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
drivers/acpi/acpi_configfs.c | 7 +-
drivers/acpi/property.c | 44 ++++--
drivers/amba/bus.c | 20 +--
drivers/ata/ahci_brcm.c | 14 +-
drivers/auxdisplay/ht16k33.c | 3 +-
drivers/base/regmap/regmap-sdw.c | 4 +-
drivers/block/floppy.c | 27 ++--
drivers/bluetooth/btqcomsmd.c | 27 ++--
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm_tis_core.c | 50 +------
drivers/clk/meson/clk-pll.c | 2 +-
drivers/clk/qcom/gcc-msm8998.c | 100 +++++++-------
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +++-
drivers/cpufreq/intel_pstate.c | 5 +-
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/chelsio/chtls/chtls_cm.h | 3 -
drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 125 ++++++++++--------
drivers/crypto/talitos.c | 28 ++--
drivers/crypto/talitos.h | 1 +
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +--
drivers/dma/owl-dma.c | 1 +
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
.../drm/amd/display/dc/dce/dce_transform.c | 8 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +--
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/hid/hid-core.c | 9 +-
drivers/hid/wacom_wac.c | 7 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/infiniband/core/user_mad.c | 17 ++-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 11 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 ++++++++-----
drivers/md/dm.c | 60 +++++++++
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/platform/pxa_camera.c | 3 +
.../media/platform/qcom/camss/camss-video.c | 1 +
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/tuners/qm1d1c0042.c | 4 +-
drivers/media/usb/dvb-usb-v2/lmedm04.c | 2 +-
drivers/media/usb/em28xx/em28xx-core.c | 6 +-
drivers/media/usb/tm6000/tm6000-dvb.c | 4 +
drivers/media/usb/uvc/uvc_v4l2.c | 18 +--
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/aspeed-lpc-snoop.c | 30 ++++-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/spi-nor/cadence-quadspi.c | 2 +-
drivers/mtd/spi-nor/hisi-sfc.c | 4 +-
drivers/net/ethernet/amd/xgbe/xgbe-common.h | 14 ++
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 1 +
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 3 +-
drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 39 +++++-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +-
.../net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
drivers/net/ethernet/ibm/ibmvnic.c | 16 ++-
drivers/net/ethernet/intel/i40e/i40e_main.c | 41 ++----
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/realtek/r8169.c | 4 +-
drivers/net/ethernet/sun/sunvnet_common.c | 23 +---
drivers/net/gtp.c | 5 +-
drivers/net/usb/qmi_wwan.c | 1 +
drivers/net/vxlan.c | 11 +-
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvdimm/dimm_devs.c | 18 ++-
drivers/of/fdt.c | 12 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/syscall.c | 10 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/pwm/pwm-rockchip.c | 1 -
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/s5m8767.c | 8 +-
drivers/rtc/Kconfig | 1 +
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 ++--
drivers/spi/spi-s3c24xx-fiq.S | 9 +-
drivers/spi/spi-stm32.c | 4 +
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../{mtk-hsdma.c => hsdma-mt7621.c} | 2 +-
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 +
drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 2 +-
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/usb/core/quirks.c | 9 +-
drivers/usb/dwc2/hcd.c | 15 ++-
drivers/usb/dwc2/hcd_intr.c | 14 +-
drivers/usb/dwc3/gadget.c | 19 ++-
drivers/usb/gadget/function/u_audio.c | 17 ++-
drivers/usb/musb/musb_core.c | 31 +++--
drivers/usb/serial/ftdi_sio.c | 5 +-
drivers/usb/serial/mos7720.c | 4 +-
drivers/usb/serial/mos7840.c | 4 +-
drivers/usb/serial/option.c | 3 +-
drivers/video/fbdev/Kconfig | 2 +-
drivers/watchdog/mei_wdt.c | 1 +
fs/affs/namei.c | 4 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/relocation.c | 4 +-
fs/cifs/connect.c | 1 +
fs/ext4/namei.c | 7 +-
fs/f2fs/file.c | 7 +-
fs/f2fs/inline.c | 4 +
fs/gfs2/lock_dlm.c | 8 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/ntfs/inode.c | 6 +
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 7 +-
include/linux/device-mapper.h | 5 +
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 48 ++++++-
include/linux/ipv6.h | 2 +-
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/rmap.h | 3 +-
include/net/icmp.h | 10 ++
include/net/tcp.h | 9 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/jump_label.c | 26 ++--
kernel/kexec_file.c | 5 +
kernel/module.c | 21 ++-
kernel/printk/printk_safe.c | 16 ++-
kernel/seccomp.c | 2 +
kernel/tracepoint.c | 80 ++++++++---
mm/hugetlb.c | 4 +-
mm/memory.c | 16 ++-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 34 +++++
net/ipv6/icmp.c | 19 +--
net/ipv6/ip6_icmp.c | 46 ++++++-
net/mac80211/mesh_hwmp.c | 2 +-
net/qrtr/tun.c | 12 +-
net/xfrm/xfrm_interface.c | 6 +-
scripts/Makefile | 9 +-
scripts/recordmcount.pl | 6 +-
security/commoncap.c | 12 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/key.c | 2 +
security/keys/trusted.c | 2 +-
sound/pci/hda/patch_realtek.c | 11 ++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/usb/pcm.c | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/event.c | 2 +
.../util/intel-pt-decoder/intel-pt-decoder.c | 3 +
234 files changed, 1473 insertions(+), 693 deletions(-)
rename drivers/staging/mt7621-dma/{mtk-hsdma.c => hsdma-mt7621.c} (99%)
--
2.25.1
1
244
[PATCH kernel-4.19 01/10] ext4: Fix not report exception message when mount with errors=continue
by Yang Yingliang 18 Mar '21
by Yang Yingliang 18 Mar '21
18 Mar '21
From: Ye Bin <yebin10(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 50614
CVE: NA
-----------------------------------------------
Fixes: 24d1ffda34be("ext4: don't remount read-only with errors=continue on reboot")
Signed-off-by: Ye Bin <yebin10(a)huawei.com>
Reviewed-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/ext4/super.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 15f8aeda9ee7f..18870ae874ab6 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -509,9 +509,12 @@ static void ext4_handle_error(struct super_block *sb)
if (test_opt(sb, WARN_ON_ERROR))
WARN_ON_ONCE(1);
- if (sb_rdonly(sb) || test_opt(sb, ERRORS_CONT))
+ if (sb_rdonly(sb))
return;
+ if (test_opt(sb, ERRORS_CONT))
+ goto out;
+
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
if (journal)
jbd2_journal_abort(journal, -EIO);
@@ -533,6 +536,7 @@ static void ext4_handle_error(struct super_block *sb)
sb->s_id);
}
+out:
ext4_netlink_send_info(sb, 1);
}
--
2.25.1
1
9
From: Zhang Ming <154842638(a)qq.com>
openEuler inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BPPX
CVE: NA
-----------------------------------------------------------
The default branch in switch will not run at present, but there may be related extensions in the future, which may lead to memory leakage
Signed-off-by: Zhang Ming <154842638(a)qq.com>
Reported-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Suggested-by: Jian Cheng <cj.chengjian(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
index aae585e7d7df..a4a298a455e0 100644
--- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
@@ -78,6 +78,7 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
suffix = "";
break;
default:
+ kfree(s);
return -EINVAL;
}
--
2.17.1
3
2
From: Zhang Ming <154842638(a)qq.com>
openEuler inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BPPX
CVE: NA
--------------------------------------- --------------------
The default branch in switch will not run at present, but there may be related extensions in the future, which may lead to memory leakage
Signed-off-by: Zhang Ming <154842638(a)qq.com>
Reported-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Suggested-by: Jian Cheng <cj.chengjian(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
index 4acf9234c3a5..b1d32d432556 100644
--- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
@@ -74,6 +74,7 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
suffix = "";
break;
default:
+ kfree(s);
return -EINVAL;
}
--
2.17.1
3
2
17 Mar '21
From: Zhang Ming <154842638(a)qq.com>
[PATCH v1 openEuler-21.03]arch/arm64/kernel/mpam/mpam_ctrlmon.c: fix a bug of memory leakage
openEuler inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BPPX
CVE: NA
-----------------------------------------------------------
The default branch in switch will not run at present, but there may be related extensions in the future, which may lead to memory leakage
Signed-off-by: Zhang Ming <154842638(a)qq.com>
Reported-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Suggested-by: Jian Cheng <cj.chengjian(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
index 4acf9234c3a5..b1d32d432556 100644
--- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
@@ -74,6 +74,7 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
suffix = "";
break;
default:
+ kfree(s);
return -EINVAL;
}
--
2.17.1
1
0
From: Zhang Ming <154842638(a)qq.com>
[PATCH kernel-4.19]arch/arm64/kernel/mpam/mpam_ctrlmon.c: fix a bug of memory leakage
openEuler inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BPPX
CVE: NA
-----------------------------------------------------------
The default branch in switch will not run at present, but there may be related extensions in the future, which may lead to memory leakage
Signed-off-by: Zhang Ming <154842638(a)qq.com>
Reported-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Suggested-by: Jian Cheng <cj.chengjian(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
index aae585e7d7df..a4a298a455e0 100644
--- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
@@ -78,6 +78,7 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
suffix = "";
break;
default:
+ kfree(s);
return -EINVAL;
}
--
2.17.1
1
0
1
0
CVE for openEuler 20.09
Chris Leech (2):
scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
scsi: iscsi: Verify lengths on passthrough PDUs
Jan Beulich (10):
Xen/x86: don't bail early from clear_foreign_p2m_mapping()
Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
Xen/gntdev: correct error checking in gntdev_map_grant_pages()
xen-blkback: don't "handle" error by BUG()
xen-netback: don't "handle" error by BUG()
xen-scsiback: don't "handle" error by BUG()
xen-blkback: fix error handling in xen_blkbk_map()
Xen/gnttab: handle p2m update errors on a per-slot basis
xen-netback: respect gnttab_map_refs()'s return value
Joe Perches (1):
sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
Lee Duncan (1):
scsi: iscsi: Restrict sessions and handles to admin capabilities
Miklos Szeredi (6):
ovl: pass correct flags for opening real directory
ovl: switch to mounter creds in readdir
ovl: verify permissions in ovl_path_open()
ovl: call secutiry hook in ovl_real_ioctl()
ovl: check permission to open real file
ovl: do not fail because of O_NOATIME
Stefano Stabellini (1):
xen/arm: don't ignore return errors from set_phys_to_machine
Wenchao Hao (1):
virtio-blk: modernize sysfs attribute creation
Yang Yingliang (1):
sysfs: fix kabi broken when add sysfs_emit and sysfs_emit_at
Documentation/filesystems/sysfs.txt | 8 +-
arch/arm/xen/p2m.c | 33 ++++++-
arch/x86/xen/p2m.c | 59 ++++++++---
drivers/block/virtio_blk.c | 67 +++++++------
drivers/block/xen-blkback/blkback.c | 30 +++---
drivers/net/xen-netback/netback.c | 10 +-
drivers/scsi/libiscsi.c | 148 ++++++++++++++--------------
drivers/scsi/scsi_transport_iscsi.c | 38 +++++--
drivers/xen/gntdev.c | 37 +++----
drivers/xen/xen-scsiback.c | 4 +-
fs/overlayfs/file.c | 28 ++++--
fs/overlayfs/readdir.c | 37 +++++--
fs/overlayfs/util.c | 27 ++++-
fs/sysfs/file.c | 55 +++++++++++
include/linux/sysfs.h | 16 +++
include/xen/grant_table.h | 1 +
security/security.c | 1 +
17 files changed, 419 insertions(+), 180 deletions(-)
--
2.25.1
2
24
CVE-2021-27365
CVE-2021-27363
CVE-2021-27364
Chris Leech (2):
scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
scsi: iscsi: Verify lengths on passthrough PDUs
Christoph Hellwig (1):
mm/swapfile.c: fix a comment in sys_swapon()
Darrick J. Wong (2):
mm: set S_SWAPFILE on blockdev swap devices
vfs: don't allow writes to swap files
Domenico Andreoli (1):
hibernate: Allow uswsusp to write to swap
Jan Beulich (10):
Xen/x86: don't bail early from clear_foreign_p2m_mapping()
Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
Xen/gntdev: correct error checking in gntdev_map_grant_pages()
xen-blkback: don't "handle" error by BUG()
xen-netback: don't "handle" error by BUG()
xen-scsiback: don't "handle" error by BUG()
xen-blkback: fix error handling in xen_blkbk_map()
Xen/gnttab: handle p2m update errors on a per-slot basis
xen-netback: respect gnttab_map_refs()'s return value
Joe Perches (1):
sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
Lee Duncan (1):
scsi: iscsi: Restrict sessions and handles to admin capabilities
Miaohe Lin (1):
mm/swapfile.c: fix potential memory leak in sys_swapon
Miklos Szeredi (6):
ovl: pass correct flags for opening real directory
ovl: switch to mounter creds in readdir
ovl: verify permissions in ovl_path_open()
ovl: call secutiry hook in ovl_real_ioctl()
ovl: check permission to open real file
ovl: do not fail because of O_NOATIME
Naohiro Aota (1):
mm/swapfile.c: move inode_lock out of claim_swapfile
Stefano Stabellini (1):
xen/arm: don't ignore return errors from set_phys_to_machine
Wenchao Hao (2):
nvme: register ns_id attributes as default sysfs groups
virtio-blk: modernize sysfs attribute creation
Yang Yingliang (1):
sysfs: fix kabi broken when add sysfs_emit and sysfs_emit_at
Ye Bin (1):
ext4: Fix not report exception message when mount with errors=continue
zhangyi (F) (1):
block_dump: remove block_dump feature when dirting inode
Documentation/filesystems/sysfs.txt | 8 +-
arch/arm/xen/p2m.c | 33 ++++++-
arch/x86/xen/p2m.c | 59 ++++++++---
drivers/block/virtio_blk.c | 67 +++++++------
drivers/block/xen-blkback/blkback.c | 30 +++---
drivers/net/xen-netback/netback.c | 10 +-
drivers/nvme/host/core.c | 20 ++--
drivers/nvme/host/lightnvm.c | 105 +++++++++-----------
drivers/nvme/host/multipath.c | 11 +--
drivers/nvme/host/nvme.h | 10 +-
drivers/scsi/libiscsi.c | 148 ++++++++++++++--------------
drivers/scsi/scsi_transport_iscsi.c | 38 +++++--
drivers/xen/gntdev.c | 37 +++----
drivers/xen/xen-scsiback.c | 4 +-
fs/block_dev.c | 5 +
fs/ext4/super.c | 6 +-
fs/fs-writeback.c | 25 -----
fs/overlayfs/file.c | 28 ++++--
fs/overlayfs/readdir.c | 37 +++++--
fs/overlayfs/util.c | 27 ++++-
fs/sysfs/file.c | 55 +++++++++++
include/linux/fs.h | 11 +++
include/linux/sysfs.h | 16 +++
include/xen/grant_table.h | 1 +
mm/filemap.c | 3 +
mm/memory.c | 4 +
mm/mmap.c | 8 +-
mm/swapfile.c | 72 ++++++++------
security/security.c | 1 +
29 files changed, 552 insertions(+), 327 deletions(-)
--
2.25.1
1
32
12 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
One cpu in PARK state could not come up in this case:
CPU 0 | CPU 1
boot_secondary(cpu 1) |
--> write_park_exit(cpu 1) |
| cpu uping from PARK
| ...
uninstall_cpu_park() |
--> memset to 0 park text |
| ...
| Exception in memory !!
wait for cpu up |
Cpu 1 uping from PARK may trap into exception while cpu 0
clear cpu 1's park text memory.
This uninstall_cpu_park should be after waiting for cpu up.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/kernel/smp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index d7b750a..fb6007d 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -300,15 +300,15 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
-#ifdef CONFIG_ARM64_CPU_PARK
- uninstall_cpu_park(cpu);
-#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
*/
wait_for_completion_timeout(&cpu_running,
msecs_to_jiffies(5000));
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
if (cpu_online(cpu))
return 0;
--
2.9.5
2
1
12 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
One cpu in PARK state could not come up in this case:
CPU 0 | CPU 1
boot_secondary(cpu 1) |
--> write_park_exit(cpu 1) |
| cpu uping from PARK
| ...
uninstall_cpu_park() |
--> memset to 0 park text |
| ...
| Exception in memory !!
wait for cpu up |
Cpu 1 uping from PARK may trap into exception while cpu 0
clear cpu 1's park text memory.
This uninstall_cpu_park should be after waiting for cpu up.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/kernel/smp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index d7b750a..fb6007d 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -300,15 +300,15 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
-#ifdef CONFIG_ARM64_CPU_PARK
- uninstall_cpu_park(cpu);
-#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
*/
wait_for_completion_timeout(&cpu_running,
msecs_to_jiffies(5000));
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
if (cpu_online(cpu))
return 0;
--
2.9.5
1
0
[PATCH openEuler-21.03 v2] park: Reserve park mem before kexec reserved
by sangyan@huawei.com 12 Mar '21
by sangyan@huawei.com 12 Mar '21
12 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
reserve_crashkernel or reserve_quick_kexec may find one sutiable
memory region and reserves it, which address of the region is
not fixed.
As a result, cpu park reserves memory could be failed while
specified address used by crashkernel or quickkexec.
So, move reserve_park_mem before reserve_crashkernel and
reserve_quick_kexec.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/mm/init.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b343744..dbcc801 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -497,16 +497,25 @@ void __init arm64_memblock_init(void)
else
arm64_dma32_phys_limit = PHYS_MASK + 1;
+ /*
+ * Reserve park memory before crashkernel and quick kexec.
+ * Because park memory must be specified by address, but
+ * crashkernel and quickkexec may be specified by memory length,
+ * then find one sutiable memory region to reserve.
+ *
+ * So reserve park memory firstly is better, but it may cause
+ * crashkernel or quickkexec reserving failed.
+ */
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_crashkernel();
#ifdef CONFIG_QUICK_KEXEC
reserve_quick_kexec();
#endif
-#ifdef CONFIG_ARM64_CPU_PARK
- reserve_park_mem();
-#endif
-
reserve_pin_memory_res();
reserve_elfcorehdr();
--
2.9.5
1
0
12 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
---
arch/arm64/Kconfig | 21 +++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 10 ++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 ++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137ab..326f26d40 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c6d..be996f3c1 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d31a..84c71c88d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b3437440d..f22faea1a 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb38b..ce4de7526 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..6f8dc9242 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.19.1
1
1
raspberrypi inclusion
category: feature
bugzilla: 50432
------------------------------
This patch adjusts following arch arm related patches for
raspberry pi on non-Raspberry Pi platforms, using specific
config CONFIG_OPENEULER_RASPBERRYPI to distinguish them:
d5c13edbd8 Improve __copy_to_user and __copy_from_user performance
97145d2a6a Update vfpmodule.c
bffc462cbd Main bcm2708/bcm2709 linux port
588cfce788 cache: export clean and invalidate
41cd350cca ARM: Activate FIQs to avoid __irq_startup warnings
90607c7aaf ARM: proc-v7: Force misalignment of early stmia
ee46d0fadf reboot: Use power off rather than busy spinning when
halt is requested
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
arch/arm/include/asm/string.h | 2 ++
arch/arm/include/asm/uaccess.h | 2 ++
arch/arm/kernel/fiq.c | 4 ++++
arch/arm/kernel/reboot.c | 6 ++++++
arch/arm/lib/Makefile | 15 +++++++++++++++
arch/arm/lib/copy_from_user.S | 6 ++++++
arch/arm/lib/uaccess_with_memcpy.c | 22 +++++++++++++++++++++-
arch/arm/mm/cache-v6.S | 8 ++++++++
arch/arm/mm/cache-v7.S | 8 ++++++++
arch/arm/mm/proc-v6.S | 8 ++++++++
arch/arm/mm/proc-v7.S | 8 ++++++++
arch/arm/vfp/vfpmodule.c | 26 ++++++++++++++++++++++++++
12 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index c22d5869e7b6..3c4ae6b3c3a6 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -45,10 +45,12 @@ static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n)
return __memset64(p, v, n * 8, v >> 32);
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
#ifdef CONFIG_BCM2835_FAST_MEMCPY
#define __HAVE_ARCH_MEMCMP
extern int memcmp(const void *, const void *, size_t);
#endif
+#endif
/*
* For files that are not instrumented (e.g. mm/slub.c) we
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index f24d3fabccd6..0d8cba7a9dde 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -516,8 +516,10 @@ do { \
extern unsigned long __must_check
arm_copy_from_user(void *to, const void __user *from, unsigned long n);
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
extern unsigned long __must_check
__copy_from_user_std(void *to, const void __user *from, unsigned long n);
+#endif
static inline unsigned long __must_check
raw_copy_from_user(void *to, const void __user *from, unsigned long n)
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index c3fe7d3cf482..8116f1e52e1b 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -56,7 +56,9 @@
static unsigned long dfl_fiq_insn;
static struct pt_regs dfl_fiq_regs;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
extern int irq_activate(struct irq_desc *desc);
+#endif
/* Default reacquire function
* - we always relinquish FIQ control
@@ -142,8 +144,10 @@ static int fiq_start;
void enable_fiq(int fiq)
{
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
struct irq_desc *desc = irq_to_desc(fiq + fiq_start);
irq_activate(desc);
+#endif
enable_irq(fiq + fiq_start);
}
diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c
index 63373adab475..ffb170568dcc 100644
--- a/arch/arm/kernel/reboot.c
+++ b/arch/arm/kernel/reboot.c
@@ -102,7 +102,13 @@ void machine_shutdown(void)
*/
void machine_halt(void)
{
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
machine_power_off();
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ local_irq_disable();
+ smp_send_stop();
+ while (1);
+#endif
}
/*
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 8271cde92dec..63820a487d4b 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -5,6 +5,7 @@
# Copyright (C) 1995-2000 Russell King
#
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
lib-y := changebit.o csumipv6.o csumpartial.o \
csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
delay.o delay-loop.o findbit.o memchr.o \
@@ -15,6 +16,18 @@ lib-y := changebit.o csumipv6.o csumpartial.o \
ucmpdi2.o lib1funcs.o div64.o \
io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
call_with_stack.o bswapsdi2.o
+else
+lib-y := changebit.o csumipv6.o csumpartial.o \
+ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
+ delay.o delay-loop.o findbit.o memchr.o memcpy.o \
+ memmove.o memset.o setbit.o \
+ strchr.o strrchr.o \
+ testchangebit.o testclearbit.o testsetbit.o \
+ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+ ucmpdi2.o lib1funcs.o div64.o \
+ io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
+ call_with_stack.o bswapsdi2.o
+endif
mmu-y := clear_user.o copy_page.o getuser.o putuser.o \
copy_from_user.o copy_to_user.o
@@ -25,6 +38,7 @@ else
lib-y += backtrace.o
endif
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
# Choose optimised implementations for Raspberry Pi
ifeq ($(CONFIG_BCM2835_FAST_MEMCPY),y)
CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600
@@ -34,6 +48,7 @@ ifeq ($(CONFIG_BCM2835_FAST_MEMCPY),y)
else
lib-y += memcpy.o memmove.o memset.o
endif
+endif
# using lib_ here won't override already available weak symbols
obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
index ab7bf28dbec0..3f83d8b18b0d 100644
--- a/arch/arm/lib/copy_from_user.S
+++ b/arch/arm/lib/copy_from_user.S
@@ -107,8 +107,12 @@
.text
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(__copy_from_user_std)
WEAK(arm_copy_from_user)
+#else
+ENTRY(arm_copy_from_user)
+#endif
#ifdef CONFIG_CPU_SPECTRE
get_thread_info r3
ldr r3, [r3, #TI_ADDR_LIMIT]
@@ -118,7 +122,9 @@ WEAK(arm_copy_from_user)
#include "copy_template.S"
ENDPROC(arm_copy_from_user)
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENDPROC(__copy_from_user_std)
+#endif
.pushsection .text.fixup,"ax"
.align 0
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index b483e5713039..ab15ed7f599a 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -19,6 +19,7 @@
#include <asm/current.h>
#include <asm/page.h>
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
#ifndef COPY_FROM_USER_THRESHOLD
#define COPY_FROM_USER_THRESHOLD 64
#endif
@@ -26,6 +27,7 @@
#ifndef COPY_TO_USER_THRESHOLD
#define COPY_TO_USER_THRESHOLD 64
#endif
+#endif
static int
pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
@@ -51,7 +53,11 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
return 0;
pmd = pmd_offset(pud, addr);
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
+#else
+ if (unlikely(pmd_none(*pmd)))
+#endif
return 0;
/*
@@ -94,6 +100,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
return 1;
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
static int
pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
{
@@ -132,8 +139,13 @@ pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
return 1;
}
+#endif
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
unsigned long noinline
+#else
+static unsigned long noinline
+#endif
__copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
{
unsigned long ua_flags;
@@ -186,6 +198,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
return n;
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
unsigned long noinline
__copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
{
@@ -236,6 +249,7 @@ __copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
out:
return n;
}
+#endif
unsigned long
arm_copy_to_user(void __user *to, const void *from, unsigned long n)
@@ -247,7 +261,11 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
* With frame pointer disabled, tail call optimization kicks in
* as well making this test almost invisible.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
if (n < COPY_TO_USER_THRESHOLD) {
+#else
+ if (n < 64) {
+#endif
unsigned long ua_flags = uaccess_save_and_enable();
n = __copy_to_user_std(to, from, n);
uaccess_restore(ua_flags);
@@ -258,6 +276,7 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
return n;
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
unsigned long __must_check
arm_copy_from_user(void *to, const void __user *from, unsigned long n)
{
@@ -283,7 +302,8 @@ arm_copy_from_user(void *to, const void __user *from, unsigned long n)
#endif
return n;
}
-
+#endif
+
static unsigned long noinline
__clear_user_memset(void __user *addr, unsigned long n)
{
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 868011801521..614d4ff2a760 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -198,7 +198,11 @@ ENTRY(v6_flush_kern_dcache_area)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(v6_dma_inv_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v6_dma_inv_range:
+#endif
#ifdef CONFIG_DMA_CACHE_RWFO
ldrb r2, [r0] @ read for ownership
strb r2, [r0] @ write for ownership
@@ -243,7 +247,11 @@ ENTRY(v6_dma_inv_range)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(v6_dma_clean_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v6_dma_clean_range:
+#endif
bic r0, r0, #D_CACHE_LINE_SIZE - 1
1:
#ifdef CONFIG_DMA_CACHE_RWFO
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 536df5db66e4..58df59734e40 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -363,8 +363,12 @@ ENDPROC(v7_flush_kern_dcache_area)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(b15_dma_inv_range)
ENTRY(v7_dma_inv_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v7_dma_inv_range:
+#endif
dcache_line_size r2, r3
sub r3, r2, #1
tst r0, r3
@@ -394,8 +398,12 @@ ENDPROC(v7_dma_inv_range)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(b15_dma_clean_range)
ENTRY(v7_dma_clean_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v7_dma_clean_range:
+#endif
dcache_line_size r2, r3
sub r3, r2, #1
bic r0, r0, r3
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index b3a2fce22eac..b651eaa1ee40 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -71,6 +71,7 @@ ENDPROC(cpu_v6_reset)
* IRQs are already disabled.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* See jira SW-5991 for details of this workaround */
ENTRY(cpu_v6_do_idle)
.align 5
@@ -84,6 +85,13 @@ ENTRY(cpu_v6_do_idle)
nop
bne 1b
ret lr
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ENTRY(cpu_v6_do_idle)
+ mov r1, #0
+ mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
+ mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt
+ ret lr
+#endif
ENTRY(cpu_v6_dcache_clean_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 3e77e8982df3..ef0e00249515 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -287,8 +287,10 @@ __v7_ca17mp_setup:
mov r10, #0
1: adr r0, __v7_setup_stack_ptr
ldr r12, [r0]
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
tst r12, #0x1f
addeq r12, r12, #4
+#endif
add r12, r12, r0 @ the local stack
stmia r12, {r1-r6, lr} @ v7_invalidate_l1 touches r0-r6
bl v7_invalidate_l1
@@ -476,8 +478,10 @@ __v7_setup:
adr r0, __v7_setup_stack_ptr
ldr r12, [r0]
add r12, r12, r0 @ the local stack
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
tst r12, #0x1f
addeq r12, r12, #4
+#endif
stmia r12, {r1-r6, lr} @ v7_invalidate_l1 touches r0-r6
bl v7_invalidate_l1
ldmia r12, {r1-r6, lr}
@@ -561,7 +565,11 @@ ENDPROC(__v7_setup)
.bss
.align 2
__v7_setup_stack:
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
.space 4 * 8 @ 7 registers + 1 spare
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ .space 4 * 7 @ 7 registers
+#endif
__INITDATA
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 1e2dcf81aefa..f7238e00db7c 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -176,11 +176,16 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
* case the thread migrates to a different CPU. The
* restoring is done lazily.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) {
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, fpexc & ~FPEXC_EX);
vfp_save_state(vfp_current_hw_state[cpu], fpexc);
}
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
+ vfp_save_state(vfp_current_hw_state[cpu], fpexc);
+#endif
#endif
/*
@@ -457,16 +462,22 @@ static int vfp_pm_suspend(void)
/* if vfp is on, then save state for resumption */
if (fpexc & FPEXC_EN) {
pr_debug("%s: saving vfp state\n", __func__);
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, fpexc & ~FPEXC_EX);
+#endif
vfp_save_state(&ti->vfpstate, fpexc);
/* disable, just in case */
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
} else if (vfp_current_hw_state[ti->cpu]) {
#ifndef CONFIG_SMP
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ fmxr(FPEXC, fpexc | FPEXC_EN);
+#endif
vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
fmxr(FPEXC, fpexc);
#endif
@@ -529,8 +540,12 @@ void vfp_sync_hwstate(struct thread_info *thread)
/*
* Save the last VFP state on this CPU.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ fmxr(FPEXC, fpexc | FPEXC_EN);
+#endif
vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
fmxr(FPEXC, fpexc);
}
@@ -596,7 +611,9 @@ int vfp_restore_user_hwstate(struct user_vfp *ufp, struct user_vfp_exc *ufp_exc)
struct thread_info *thread = current_thread_info();
struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
unsigned long fpexc;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
u32 fpsid = fmrx(FPSID);
+#endif
/* Disable VFP to avoid corrupting the new thread state. */
vfp_flush_hwstate(thread);
@@ -619,11 +636,16 @@ int vfp_restore_user_hwstate(struct user_vfp *ufp, struct user_vfp_exc *ufp_exc)
/* Ensure the VFP is enabled. */
fpexc |= FPEXC_EN;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */
if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) {
/* Ensure FPINST2 is invalid and the exception flag is cleared. */
fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
}
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ /* Ensure FPINST2 is invalid and the exception flag is cleared. */
+ fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
+#endif
hwstate->fpexc = fpexc;
@@ -738,8 +760,12 @@ void kernel_neon_begin(void)
cpu = get_cpu();
fpexc = fmrx(FPEXC) | FPEXC_EN;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, fpexc & ~FPEXC_EX);
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ fmxr(FPEXC, fpexc);
+#endif
/*
* Save the userland NEON/VFP state. Under UP,
--
2.20.1
2
1
[PATCH openEuler-1.0-LTS] sysctl: control if check validity of freelist and connector debug by sysctl
by Cheng Jian 11 Mar '21
by Cheng Jian 11 Mar '21
11 Mar '21
From: Yang Yingliang <yangyingliang(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 47452
CVE: NA
-------------------------------------------------
Change control methods of check validity of freelist and
connector debug to sysctl.
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
drivers/connector/connector.c | 1 +
include/linux/slab.h | 4 ---
kernel/sysctl.c | 20 +++++++++++
mm/slub.c | 63 ++++++++++++++---------------------
4 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index a8df9ecbf42b..b5cdd0b99736 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -42,6 +42,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
static struct cn_dev cdev;
static int cn_already_initialized;
+int sysctl_connector_debug = 0;
/*
* Sends mult (multiple) cn_msg at a time.
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 1ab5fd97dec8..d6393413ef09 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -24,8 +24,6 @@
*/
/* DEBUG: Perform (expensive) checks on alloc/free */
#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100U)
-/* Check if freelist is valid */
-#define SLAB_NO_FREELIST_CHECKS ((slab_flags_t __force)0x00000200U)
/* DEBUG: Red zone objs in a cache */
#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)
/* DEBUG: Poison objects */
@@ -113,8 +111,6 @@
#define SLAB_KASAN 0
#endif
-#define SLAB_CONNECTOR_DEBUG ((slab_flags_t __force)0x10000000U)
-
/* The following flags affect the page allocator grouping pages by mobility */
/* Objects are reclaimable */
#define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000U)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 665c9e2a8802..c921ee10615a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1245,6 +1245,7 @@ static struct ctl_table kern_table[] = {
{ }
};
+extern int sysctl_isolate_corrupted_freelist;
static struct ctl_table vm_table[] = {
{
.procname = "overcommit_memory",
@@ -1714,6 +1715,15 @@ static struct ctl_table vm_table[] = {
.extra2 = (void *)&mmap_rnd_compat_bits_max,
},
#endif
+ {
+ .procname = "isolate_corrupted_freelist",
+ .data = &sysctl_isolate_corrupted_freelist,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{ }
};
@@ -1925,6 +1935,7 @@ static struct ctl_table fs_table[] = {
{ }
};
+extern int sysctl_connector_debug;
static struct ctl_table debug_table[] = {
#ifdef CONFIG_SYSCTL_EXCEPTION_TRACE
{
@@ -1946,6 +1957,15 @@ static struct ctl_table debug_table[] = {
.extra2 = &one,
},
#endif
+ {
+ .procname = "connector-debug",
+ .data = &sysctl_connector_debug,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{ }
};
diff --git a/mm/slub.c b/mm/slub.c
index ee0d18699bde..2301c04353d0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1221,30 +1221,6 @@ static noinline int free_debug_processing(
return ret;
}
-/*
- * Check if the next object in freechain is
- * valid, then isolate the corrupted freelist.
- */
-int isolate_cnt = 0;
-static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page,
- void **freelist, void *next)
-{
- if (!(slub_debug & SLAB_NO_FREELIST_CHECKS) &&
- (!check_valid_pointer(s, page, next))) {
- /* Need caller make sure freelist is not NULL */
- *freelist = NULL;
- isolate_cnt++;
-
- slab_fix(s, "Freelist corrupt,isolate corrupted freechain.");
- pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n",
- (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page);
-
- return true;
- }
-
- return false;
-}
-
static int __init setup_slub_debug(char *str)
{
slub_debug = DEBUG_DEFAULT_FLAGS;
@@ -1291,14 +1267,6 @@ static int __init setup_slub_debug(char *str)
case 'a':
slub_debug |= SLAB_FAILSLAB;
break;
- case 'n':
- slub_debug |= SLAB_NO_FREELIST_CHECKS;
- pr_info("Freelist pointer check disabled.");
- break;
- case 'd':
- slub_debug |= SLAB_CONNECTOR_DEBUG;
- pr_info("Connector debug enabled.\n");
- break;
case 'o':
/*
* Avoid enabling debugging on caches if its minimum
@@ -1311,8 +1279,6 @@ static int __init setup_slub_debug(char *str)
*str);
}
}
- if (!(slub_debug & SLAB_NO_FREELIST_CHECKS))
- pr_info("Freelist pointer check enabled.");
check_slabs:
if (*str == ',')
@@ -1380,12 +1346,33 @@ static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
{
return false;
}
+#endif /* CONFIG_SLUB_DEBUG */
+
+extern int sysctl_connector_debug;
+/*
+ * Check if the next object in freechain is
+ * valid, then isolate the corrupted freelist.
+ */
+int isolate_cnt = 0;
+int sysctl_isolate_corrupted_freelist = 1;
static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page,
- void **freelist, void *nextfree)
+ void **freelist, void *next)
{
+ if (sysctl_isolate_corrupted_freelist &&
+ (!check_valid_pointer(s, page, next))) {
+ /* Need caller make sure freelist is not NULL */
+ *freelist = NULL;
+ isolate_cnt++;
+
+ slab_fix(s, "Freelist corrupt,isolate corrupted freechain.");
+ pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n",
+ (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page);
+
+ return true;
+ }
+
return false;
}
-#endif /* CONFIG_SLUB_DEBUG */
/*
* Hooks for other subsystems that check memory allocations. In a typical
@@ -2798,7 +2785,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
if (unlikely(gfpflags & __GFP_ZERO) && object)
memset(object, 0, s->object_size);
- if ((slub_debug & SLAB_CONNECTOR_DEBUG) &&
+ if (sysctl_connector_debug &&
unlikely(gfpflags & __GFP_CONNECTOR) && object) {
if (s->object_size == 512)
memset(object + 504, 0xad, 8);
@@ -4015,7 +4002,7 @@ void kfree(const void *x)
__free_pages(page, compound_order(page));
return;
}
- if ((slub_debug & SLAB_CONNECTOR_DEBUG) &&
+ if (sysctl_connector_debug &&
unlikely(page->slab_cache->object_size == 512)) {
u64 *tail = (u64 *)(x + 504);
--
2.25.1
1
0
bugfix for 20.03 at 202102
Alexey Gladkov (1):
moduleparam: Save information about built-in modules in separate file
Amir Goldstein (1):
ovl: skip getxattr of security labels
Aurelien Aptel (1):
cifs: report error instead of invalid when revalidating a dentry fails
Baptiste Lepers (1):
udp: Prevent reuseport_select_sock from reading uninitialized socks
Byron Stanoszek (1):
tmpfs: restore functionality of nr_inodes=0
Chris Down (2):
tmpfs: per-superblock i_ino support
tmpfs: support 64-bit inums per-sb
Christian Brauner (1):
sysctl: handle overflow in proc_get_long
Cong Wang (1):
af_key: relax availability checks for skb size calculation
Dave Wysochanski (2):
SUNRPC: Move simple_get_bytes and simple_get_netobj into private
header
SUNRPC: Handle 0 length opaque XDR object data properly
Dong Kai (1):
livepatch/core: Fix jump_label_apply_nops called multi times
Edwin Peer (1):
net: watchdog: hold device global xmit lock during tx disable
Eric Biggers (1):
fs: fix lazytime expiration handling in __writeback_single_inode()
Eric Dumazet (1):
net_sched: gen_estimator: support large ewma log
Eyal Birger (1):
xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
Florian Westphal (1):
netfilter: conntrack: skip identical origin tuple in same zone only
Gaurav Kohli (1):
tracing: Fix race in trace_open and buffer resize call
Gustavo A. R. Silva (1):
smb3: Fix out-of-bounds bug in SMB2_negotiate()
Hugh Dickins (1):
mm: thp: fix MADV_REMOVE deadlock on shmem THP
Jakub Kicinski (1):
net: sit: unregister_netdevice on newlink's error path
Jan Kara (1):
writeback: Drop I_DIRTY_TIME_EXPIRE
Jozsef Kadlecsik (1):
netfilter: xt_recent: Fix attempt to update deleted entry
Liangyan (1):
ovl: fix dentry leak in ovl_get_redirect
Lin Feng (1):
bfq-iosched: Revert "bfq: Fix computation of shallow depth"
Marc Zyngier (1):
genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is
set
Martin K. Petersen (2):
scsi: sd: block: Fix regressions in read-only block device handling
scsi: sd: block: Fix kabi change by 'scsi: sd: block: Fix regressions
in read-only block device handling'
Martin Willi (1):
vrf: Fix fast path output packet handling with async Netfilter rules
Masami Hiramatsu (1):
tracing/kprobe: Fix to support kretprobe events on unloaded modules
Miklos Szeredi (4):
proc/mounts: add cursor
ovl: perform vfs_getxattr() with mounter creds
cap: fix conversions on getxattr
ovl: expand warning in ovl_d_real()
Mikulas Patocka (1):
dm integrity: conditionally disable "recalculate" feature
Ming Lei (4):
scsi: core: Run queue in case of I/O resource contention failure
scsi: core: Only re-run queue in scsi_end_request() if device queue is
busy
block: don't hold q->sysfs_lock in elevator_init_mq
blk-mq: don't hold q->sysfs_lock in blk_mq_map_swqueue
Muchun Song (4):
mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
mm: hugetlb: fix a race between freeing and dissolving the page
mm: hugetlb: fix a race between isolating and freeing page
mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
NeilBrown (1):
net: fix iteration for sctp transport seq_files
Ondrej Jirman (1):
brcmfmac: Loading the correct firmware for brcm43456
Pablo Neira Ayuso (1):
netfilter: nft_dynset: add timeout extension to template
Pavel Begunkov (1):
list: introduce list_for_each_continue()
Pengcheng Yang (1):
tcp: fix TLP timer not set when CA_STATE changes from DISORDER to OPEN
Peter Zijlstra (2):
kthread: Extract KTHREAD_IS_PER_CPU
workqueue: Restrict affinity change to rescuer
Roi Dayan (1):
net/mlx5: Fix memory leak on flow table creation error flow
Roman Gushchin (1):
memblock: do not start bottom-up allocations with kernel_end
Sabyrzhan Tasbolatov (1):
net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
Shmulik Ladkani (1):
xfrm: Fix oops in xfrm_replay_advance_bmp
Steven Rostedt (VMware) (3):
fgraph: Initialize tracing_graph_pause at task creation
tracing: Do not count ftrace events in top level enable output
tracing: Check length before giving out the filter buffer
Sven Auhagen (1):
netfilter: flowtable: fix tcp and udp header checksum update
Vadim Fedorenko (1):
net: ip_tunnel: fix mtu calculation
Wang Hai (1):
Revert "mm/slub: fix a memory leak in sysfs_slab_add()"
Wang ShaoBo (1):
kretprobe: Avoid re-registration of the same kretprobe earlier
Willem de Bruijn (1):
esp: avoid unneeded kmap_atomic call
Xiao Ni (1):
md: Set prev_flush_start and flush_bio in an atomic way
Yang Yingliang (3):
sysctl/mm: fix compile error when CONFIG_SLUB is disabled
config: disable config TMPFS_INODE64 by default
connector: change GFP_CONNECTOR to bit-31
Ye Bin (3):
scsi: sd: block: Fix read-only flag residuals when partition table
change
Revert "scsi: sd: block: Fix read-only flag residuals when partition
table change"
Revert "scsi: sg: fix memory leak in sg_build_indirect"
Yonglong Liu (4):
net: hns3: adds support for setting pf max tx rate via sysfs
net: hns3: update hns3 version to 1.9.38.10
net: hns3: fix 'ret' may be used uninitialized problem
net: hns3: update hns3 version to 1.9.38.11
Yufen Yu (1):
scsi: fix kabi for scsi_device
Zhang Xiaoxu (1):
proc/mounts: Fix kabi broken
liubo (3):
etmem: add etmem-scan feature
etmem: add etmem-swap feature
config: Enable the config option of the etmem feature
shiyongbang (3):
gpu: hibmc: Fix erratic display during startup stage.
gpu: hibmc: Use drm get pci dev api.
gpu: hibmc: Fix stuck when switch GUI to text.
zhangyi (F) (1):
ext4: find old entry again if failed to rename whiteout
.gitignore | 1 +
Documentation/device-mapper/dm-integrity.txt | 7 +
Documentation/dontdiff | 1 +
Documentation/filesystems/tmpfs.txt | 17 +
Documentation/kbuild/kbuild.txt | 5 +
Makefile | 2 +
arch/arm64/configs/hulk_defconfig | 3 +
arch/arm64/configs/openeuler_defconfig | 2 +
arch/x86/configs/hulk_defconfig | 2 +
arch/x86/configs/openeuler_defconfig | 2 +
block/bfq-iosched.c | 8 +-
block/blk-mq.c | 7 -
block/elevator.c | 14 +-
block/genhd.c | 33 +-
block/ioctl.c | 4 +
block/partition-generic.c | 7 +-
drivers/connector/connector.c | 6 +-
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 68 +-
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 +
.../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 1 +
drivers/md/dm-integrity.c | 24 +-
drivers/md/md.c | 2 +
drivers/net/ethernet/hisilicon/hns3/Makefile | 3 +-
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 10 +-
.../hns3/hns3_cae/hns3_cae_version.h | 2 +-
.../net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +-
.../hns3_extension/hns3pf/hclge_main_it.c | 33 +
.../hns3/hns3_extension/hns3pf/hclge_sysfs.c | 140 +++
.../hns3/hns3_extension/hns3pf/hclge_sysfs.h | 14 +
.../hisilicon/hns3/hns3pf/hclge_main.c | 17 +
.../hisilicon/hns3/hns3pf/hclge_main.h | 7 +-
.../hisilicon/hns3/hns3vf/hclgevf_main.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/fs_core.c | 1 +
drivers/net/vrf.c | 92 +-
.../broadcom/brcm80211/brcmfmac/sdio.c | 4 +-
drivers/scsi/scsi_lib.c | 59 +-
drivers/scsi/sg.c | 6 +-
fs/Kconfig | 21 +
fs/cifs/dir.c | 22 +-
fs/cifs/smb2pdu.h | 2 +-
fs/ext4/inode.c | 2 +-
fs/ext4/namei.c | 29 +-
fs/fs-writeback.c | 36 +-
fs/hugetlbfs/inode.c | 3 +-
fs/mount.h | 17 +-
fs/namespace.c | 119 +-
fs/overlayfs/copy_up.c | 15 +-
fs/overlayfs/dir.c | 2 +-
fs/overlayfs/inode.c | 2 +
fs/overlayfs/super.c | 13 +-
fs/proc/Makefile | 2 +
fs/proc/base.c | 4 +
fs/proc/etmem_scan.c | 1046 +++++++++++++++++
fs/proc/etmem_scan.h | 132 +++
fs/proc/etmem_swap.c | 102 ++
fs/proc/internal.h | 2 +
fs/proc/task_mmu.c | 117 ++
fs/proc_namespace.c | 4 +-
fs/xfs/xfs_trans_inode.c | 4 +-
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/fs.h | 16 +-
include/linux/genhd.h | 5 +
include/linux/gfp.h | 8 +-
include/linux/hugetlb.h | 3 +
include/linux/kprobes.h | 2 +-
include/linux/kthread.h | 3 +
include/linux/list.h | 10 +
include/linux/mm_types.h | 18 +
include/linux/module.h | 1 +
include/linux/moduleparam.h | 12 +-
include/linux/mount.h | 4 +-
include/linux/msi.h | 6 +
include/linux/netdevice.h | 2 +
include/linux/shmem_fs.h | 3 +
include/linux/sunrpc/xdr.h | 3 +-
include/linux/swap.h | 5 +
include/net/tcp.h | 2 +-
include/scsi/scsi_device.h | 3 +-
include/trace/events/writeback.h | 1 -
init/init_task.c | 3 +-
kernel/irq/msi.c | 44 +-
kernel/kprobes.c | 36 +-
kernel/kthread.c | 27 +-
kernel/livepatch/core.c | 20 +-
kernel/smpboot.c | 1 +
kernel/sysctl.c | 6 +
kernel/trace/ftrace.c | 2 -
kernel/trace/ring_buffer.c | 4 +
kernel/trace/trace.c | 2 +-
kernel/trace/trace_events.c | 3 +-
kernel/trace/trace_kprobe.c | 4 +-
kernel/workqueue.c | 9 +-
lib/Kconfig | 11 +
mm/huge_memory.c | 37 +-
mm/hugetlb.c | 48 +-
mm/memblock.c | 49 +-
mm/pagewalk.c | 1 +
mm/shmem.c | 133 ++-
mm/slub.c | 14 +-
mm/vmscan.c | 112 ++
mm/vmstat.c | 4 +
net/core/gen_estimator.c | 11 +-
net/core/sock_reuseport.c | 2 +-
net/ipv4/esp4.c | 7 +-
net/ipv4/ip_tunnel.c | 16 +-
net/ipv4/tcp_input.c | 10 +-
net/ipv4/tcp_recovery.c | 5 +-
net/ipv6/esp6.c | 7 +-
net/ipv6/sit.c | 5 +-
net/key/af_key.c | 6 +-
net/netfilter/nf_conntrack_core.c | 3 +-
net/netfilter/nf_flow_table_core.c | 4 +-
net/netfilter/nft_dynset.c | 4 +-
net/netfilter/xt_recent.c | 12 +-
net/rds/rdma.c | 3 +
net/sctp/proc.c | 16 +-
net/sunrpc/auth_gss/auth_gss.c | 30 +-
net/sunrpc/auth_gss/auth_gss_internal.h | 45 +
net/sunrpc/auth_gss/gss_krb5_mech.c | 31 +-
net/xfrm/xfrm_input.c | 2 +-
net/xfrm/xfrm_policy.c | 4 +-
scripts/link-vmlinux.sh | 3 +
security/commoncap.c | 67 +-
virt/kvm/kvm_main.c | 6 +
124 files changed, 2817 insertions(+), 466 deletions(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.h
create mode 100644 fs/proc/etmem_scan.c
create mode 100644 fs/proc/etmem_scan.h
create mode 100644 fs/proc/etmem_swap.c
create mode 100644 net/sunrpc/auth_gss/auth_gss_internal.h
--
2.25.1
1
82
From: Pavel Begunkov <asml.silence(a)gmail.com>
mainline inclusion
from mainline-v5.6-rc1
commit 28ca0d6d39ab1d01c86762c82a585b7cedd2920c
category: bugfix
bugzilla: 35619
CVE: NA
--------------------------------
As other *continue() helpers, this continues iteration from a given
position.
Signed-off-by: Pavel Begunkov <asml.silence(a)gmail.com>
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5(a)huawei.com>
Reviewed-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/list.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/linux/list.h b/include/linux/list.h
index de04cc5ed536..0e540581d52c 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -455,6 +455,16 @@ static inline void list_splice_tail_init(struct list_head *list,
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
+/**
+ * list_for_each_continue - continue iteration over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * Continue to iterate over a list, continuing after the current position.
+ */
+#define list_for_each_continue(pos, head) \
+ for (pos = pos->next; pos != (head); pos = pos->next)
+
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
--
2.25.1
1
11
[PATCH openEuler-21.03 v1] park: Reserve park mem before kexec reserved
by sangyan@huawei.com 10 Mar '21
by sangyan@huawei.com 10 Mar '21
10 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
reserve_crashkernel or reserve_quick_kexec may find one sutiable
memory region and reserves it, which address of the region is
not fixed.
As a result, cpu park reserves memory could be failed while
specified address used by crashkernel or quickkexec.
So, move reserve_park_mem before reserve_crashkernel and
reserve_quick_kexec.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/mm/init.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b343744..043a981 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -497,16 +497,16 @@ void __init arm64_memblock_init(void)
else
arm64_dma32_phys_limit = PHYS_MASK + 1;
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_crashkernel();
#ifdef CONFIG_QUICK_KEXEC
reserve_quick_kexec();
#endif
-#ifdef CONFIG_ARM64_CPU_PARK
- reserve_park_mem();
-#endif
-
reserve_pin_memory_res();
reserve_elfcorehdr();
--
2.9.5
1
0
10 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 21 +++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 10 ++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 ++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137ab..326f26d40 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c6d..be996f3c1 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d31a..84c71c88d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b3437440d..f22faea1a 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb38b..ce4de7526 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..6f8dc9242 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.19.1
1
1
ok!
1
0
4
7
From: Fang Yafen <yafen(a)iscas.ac.cn>
Fix the following compile error when using bcm2711_defconfig (for RPi).
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `set -e;
echo ' DTCO arch/arm64/boot/dts/overlays/act-led.dtbo';
mkdir -p arch/arm64/boot/dts/overlays/ ;
gcc -E -Wp,-MMD,arch/arm64/boot/dts/overlays/.act-led.dtbo.d.pre.tmp
-nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__
-x assembler-with-cpp
-o arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp
arch/arm64/boot/dts/overlays/act-led-overlay.dts ;
./scripts/dtc/dtc -@ -H epapr -O dtb
-o arch/arm64/boot/dts/overlays/act-led.dtbo -b 0
-i arch/arm64/boot/dts/overlays/ -Wno-interrupt_provider
-Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-gpios_property
-Wno-avoid_unnecessary_addr_size -Wno-alias_paths
-Wno-graph_child_address -Wno-simple_bus_reg
-Wno-unique_unit_address -Wno-pci_device_reg
-Wno-interrupts_property ifeq (y,y) -Wno-label_is_string
-Wno-reg_format -Wno-pci_device_bus_num -Wno-i2c_bus_reg
-Wno-spi_bus_reg -Wno-avoid_default_addr_size endif
-d arch/arm64/boot/dts/overlays/.act-led.dtbo.d.dtc.tmp
arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp ;
cat ...; rm -f arch/arm64/boot/dts/overlays/.act-led.dtbo.d'
make[2]: *** [scripts/Makefile.lib;363:
arch/arm64/boot/dts/overlays/act-led.dtbo] Error 1
make[2]: *** Waiting for unfinished jobs....
Related patches:
ffa2d13ccc3 BCM2708: Add core Device Tree support
4894352ec98 kbuild: Silence unavoidable dtc overlay warnings
a4a4d07f0cf kbuild: keep the original function for non-RPi
Signed-off-by: Fang Yafen <yafen(a)iscas.ac.cn>
---
scripts/Makefile.lib | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index c23e3ae7ef40..a0e0e2543165 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -342,25 +342,25 @@ endef
$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_rule,dtc,yaml)
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
quiet_cmd_dtco = DTCO $@
cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -@ -H epapr -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-Wno-interrupts_property \
-ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y) \
-Wno-label_is_string \
-Wno-reg_format \
-Wno-pci_device_bus_num \
-Wno-i2c_bus_reg \
-Wno-spi_bus_reg \
-Wno-avoid_default_addr_size \
-endif \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtbo: $(src)/%-overlay.dts FORCE
$(call if_changed_dep,dtco)
+endif
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
--
2.27.0
2
1
[PATCH kernel-4.19 01/32] ascend: sharepool: don't enable the vmalloc to use hugepage default
by Yang Yingliang 08 Mar '21
by Yang Yingliang 08 Mar '21
08 Mar '21
From: Ding Tianhong <dingtianhong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
The commit 59a57a82fb2a ("mm/vmalloc: Hugepage vmalloc mappings")
would enable the vmalloc for hugepage default when the alloc size
is bigger than the PMD_SIZE, it looks like the transparent hugepage
for mmap, the driver could not control the hugepage accurately and
be break the logic, now the share pool already export the
vmalloc_hugepage_xxx function to control the vmalloc hugepage allocation,
it looks like the static hugepage for vmalloc, so disable the transparent
hugepage function.
This patch also fix the problem of breaking the kabi of vm_struct,
the user could applied it for commercial version.
Fixes: 59a57a82fb2a ("mm/vmalloc: Hugepage vmalloc mappings")
Signed-off-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/share_pool.h | 51 ++++++++++++++++++++++++++++----------
include/linux/vmalloc.h | 1 -
mm/vmalloc.c | 47 ++++++++++++-----------------------
3 files changed, 54 insertions(+), 45 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h
index c3120b7b24948..4a18c88d5a10e 100644
--- a/include/linux/share_pool.h
+++ b/include/linux/share_pool.h
@@ -211,15 +211,6 @@ static inline void sp_area_work_around(struct vm_unmapped_area_info *info)
extern struct page *sp_alloc_pages(struct vm_struct *area, gfp_t mask,
unsigned int page_order, int node);
-
-static inline void sp_free_pages(struct page *page, struct vm_struct *area)
-{
- if (PageHuge(page))
- put_page(page);
- else
- __free_pages(page, area->page_order);
-}
-
static inline bool sp_check_vm_share_pool(unsigned long vm_flags)
{
if (enable_ascend_share_pool && (vm_flags & VM_SHARE_POOL))
@@ -264,6 +255,30 @@ extern void *buff_vzalloc_hugepage_user(unsigned long size);
void sp_exit_mm(struct mm_struct *mm);
+static inline bool is_vmalloc_huge(unsigned long vm_flags)
+{
+ if (enable_ascend_share_pool && (vm_flags & VM_HUGE_PAGES))
+ return true;
+
+ return false;
+}
+
+static inline bool is_vmalloc_sharepool(unsigned long vm_flags)
+{
+ if (enable_ascend_share_pool && (vm_flags & VM_SHAREPOOL))
+ return true;
+
+ return false;
+}
+
+static inline void sp_free_pages(struct page *page, struct vm_struct *area)
+{
+ if (PageHuge(page))
+ put_page(page);
+ else
+ __free_pages(page, is_vmalloc_huge(area->flags) ? PMD_SHIFT - PAGE_SHIFT : 0);
+}
+
#else
static inline int sp_group_add_task(int pid, int spg_id)
@@ -400,10 +415,6 @@ static inline struct page *sp_alloc_pages(void *area, gfp_t mask,
return NULL;
}
-static inline void sp_free_pages(struct page *page, struct vm_struct *area)
-{
-}
-
static inline bool sp_check_vm_share_pool(unsigned long vm_flags)
{
return false;
@@ -448,6 +459,20 @@ static inline void *buff_vzalloc_hugepage_user(unsigned long size)
return NULL;
}
+static inline bool is_vmalloc_huge(struct vm_struct *vm)
+{
+ return NULL;
+}
+
+static inline bool is_vmalloc_sharepool(struct vm_struct *vm)
+{
+ return NULL;
+}
+
+static inline void sp_free_pages(struct page *page, struct vm_struct *area)
+{
+}
+
#endif
#endif /* LINUX_SHARE_POOL_H */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index bb814f6418fd9..298eff5579b21 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -43,7 +43,6 @@ struct vm_struct {
unsigned long size;
unsigned long flags;
struct page **pages;
- unsigned int page_order;
unsigned int nr_pages;
phys_addr_t phys_addr;
const void *caller;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 37b4762871142..8c70131e0b078 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2354,6 +2354,7 @@ struct vm_struct *remove_vm_area(const void *addr)
static void __vunmap(const void *addr, int deallocate_pages)
{
struct vm_struct *area;
+ unsigned int page_order = 0;
if (!addr)
return;
@@ -2369,13 +2370,14 @@ static void __vunmap(const void *addr, int deallocate_pages)
return;
}
-#ifdef CONFIG_ASCEND_SHARE_POOL
/* unmap a sharepool vm area will cause meamleak! */
- if (area->flags & VM_SHAREPOOL) {
+ if (is_vmalloc_sharepool(area->flags)) {
WARN(1, KERN_ERR "Memory leak due to vfree() sharepool vm area (%p) !\n", addr);
return;
}
-#endif
+
+ if (is_vmalloc_huge(area->flags))
+ page_order = PMD_SHIFT - PAGE_SHIFT;
debug_check_no_locks_freed(area->addr, get_vm_area_size(area));
debug_check_no_obj_freed(area->addr, get_vm_area_size(area));
@@ -2384,14 +2386,14 @@ static void __vunmap(const void *addr, int deallocate_pages)
if (deallocate_pages) {
int i;
- for (i = 0; i < area->nr_pages; i += 1U << area->page_order) {
+ for (i = 0; i < area->nr_pages; i += 1U << page_order) {
struct page *page = area->pages[i];
BUG_ON(!page);
if (sp_is_enabled())
sp_free_pages(page, area);
else
- __free_pages(page, area->page_order);
+ __free_pages(page, page_order);
}
kvfree(area->pages);
@@ -2589,7 +2591,6 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
area->pages = pages;
area->nr_pages = nr_pages;
- area->page_order = page_order;
for (i = 0; i < area->nr_pages; i += 1U << page_order) {
struct page *page;
@@ -2657,27 +2658,17 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
if (!size || (size >> PAGE_SHIFT) > totalram_pages)
goto fail;
- if (vmap_allow_huge && (pgprot_val(prot) == pgprot_val(PAGE_KERNEL))) {
- unsigned long size_per_node;
-
+ if (vmap_allow_huge && (pgprot_val(prot) == pgprot_val(PAGE_KERNEL)) && is_vmalloc_huge(vm_flags)) {
/*
- * Try huge pages. Only try for PAGE_KERNEL allocations,
- * others like modules don't yet expect huge pages in
- * their allocations due to apply_to_page_range not
- * supporting them.
+ * Alloc huge pages. Only valid for PAGE_KERNEL allocations and
+ * VM_HUGE_PAGES flags.
*/
- size_per_node = size;
- if (node == NUMA_NO_NODE && !sp_is_enabled())
- size_per_node /= num_online_nodes();
- if (size_per_node >= PMD_SIZE) {
- shift = PMD_SHIFT;
- align = max(real_align, 1UL << shift);
- size = ALIGN(real_size, 1UL << shift);
- }
+ shift = PMD_SHIFT;
+ align = max(real_align, 1UL << shift);
+ size = ALIGN(real_size, 1UL << shift);
}
-again:
size = PAGE_ALIGN(size);
area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
vm_flags, start, end, node, gfp_mask, caller);
@@ -2706,12 +2697,6 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
return addr;
fail:
- if (shift > PAGE_SHIFT) {
- shift = PAGE_SHIFT;
- align = real_align;
- size = real_size;
- goto again;
- }
if (!area) {
/* Warn for area allocation, page allocations already warn */
@@ -3776,7 +3761,7 @@ static int s_show(struct seq_file *m, void *p)
seq_printf(m, " %pS", v->caller);
if (v->nr_pages)
- seq_printf(m, " pages=%d order=%d", v->nr_pages, v->page_order);
+ seq_printf(m, " pages=%d", v->nr_pages);
if (v->phys_addr)
seq_printf(m, " phys=%pa", &v->phys_addr);
@@ -3796,8 +3781,8 @@ static int s_show(struct seq_file *m, void *p)
if (is_vmalloc_addr(v->pages))
seq_puts(m, " vpages");
- if (sp_is_enabled())
- seq_printf(m, " order=%d", v->page_order);
+ if (is_vmalloc_huge(v->flags))
+ seq_printf(m, " order=%d", PMD_SHIFT - PAGE_SHIFT);
show_numa_info(m, v);
seq_putc(m, '\n');
--
2.25.1
1
31
openEuler inclusion
category: bugfix
bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=6
CVE: NA
When performing the out-of-tree kernel 4.19 building, some error
happened saying: cannot touch 'certs/pubring.gpg'. The detail can be
checked in Gitee issue #I39160 or Bug 6 of openeuler bugzilla.
This patch will fix that build error.
Signed-off-by: Zhichang Yuan <erik.yuan(a)arm.com>
Signed-off-by: Steve Capper <Steve.Capper(a)arm.com>
---
certs/Makefile | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/certs/Makefile b/certs/Makefile
index 5053e3c86c97..5e56f9405758 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -5,11 +5,12 @@
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
ifdef CONFIG_PGP_PRELOAD_PUBLIC_KEYS
-ifneq ($(shell ls certs/pubring.gpg 2> /dev/null), certs/pubring.gpg)
-$(shell touch certs/pubring.gpg)
-endif
-$(obj)/system_certificates.o: certs/pubring.gpg
+$(obj)/system_certificates.o: $(obj)/pubring.gpg
+
+$(obj)/pubring.gpg:
+ $(Q)touch $@
endif
+
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"")
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
--
2.23.0
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
4
6
Alain Volmat (1):
i2c: stm32f7: fix configuration of the digital filter
Alexandre Belloni (1):
ARM: dts: lpc32xx: Revert set default clock rate of HCLK PLL
Alexandre Ghiti (1):
riscv: virt_addr_valid must check the address belongs to linear
mapping
Amir Goldstein (1):
ovl: skip getxattr of security labels
Arun Easi (1):
scsi: qla2xxx: Fix crash during driver load on big endian machines
Borislav Petkov (1):
x86/build: Disable CET instrumentation in the kernel for 32-bit too
Bui Quang Minh (1):
bpf: Check for integer overflow when using roundup_pow_of_two()
Edwin Peer (1):
net: watchdog: hold device global xmit lock during tx disable
Fangrui Song (1):
firmware_loader: align .builtin_fw to 8
Felipe Balbi (1):
usb: dwc3: ulpi: fix checkpatch warning
Florian Westphal (1):
netfilter: conntrack: skip identical origin tuple in same zone only
Greg Kroah-Hartman (1):
Linux 4.19.177
Hans de Goede (1):
platform/x86: hp-wmi: Disable tablet-mode reporting by default
Jan Beulich (8):
Xen/x86: don't bail early from clear_foreign_p2m_mapping()
Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
Xen/gntdev: correct error checking in gntdev_map_grant_pages()
xen-blkback: don't "handle" error by BUG()
xen-netback: don't "handle" error by BUG()
xen-scsiback: don't "handle" error by BUG()
xen-blkback: fix error handling in xen_blkbk_map()
Jozsef Kadlecsik (1):
netfilter: xt_recent: Fix attempt to update deleted entry
Juergen Gross (1):
xen/netback: avoid race in xenvif_rx_ring_slots_available()
Julien Grall (1):
arm/xen: Don't probe xenbus as part of an early initcall
Lai Jiangshan (1):
kvm: check tlbs_dirty directly
Lin Feng (1):
bfq-iosched: Revert "bfq: Fix computation of shallow depth"
Loic Poulain (1):
net: qrtr: Fix port ID for control messages
Lorenzo Bianconi (1):
mt76: dma: fix a possible memory leak in mt76_add_fragment()
Marc Zyngier (1):
arm64: dts: rockchip: Fix PCIe DT properties on rk3399
Miklos Szeredi (3):
ovl: perform vfs_getxattr() with mounter creds
cap: fix conversions on getxattr
ovl: expand warning in ovl_d_real()
Mohammad Athari Bin Ismail (1):
net: stmmac: set TxQ mode back to DCB after disabling CBS
NeilBrown (1):
net: fix iteration for sctp transport seq_files
Norbert Slusarek (1):
net/vmw_vsock: improve locking in vsock_connect_timeout()
Paolo Bonzini (1):
KVM: SEV: fix double locking due to incorrect backport
Randy Dunlap (1):
h8300: fix PREEMPTION build, TI_PRE_COUNT undefined
Russell King (2):
ARM: ensure the signal page contains defined contents
ARM: kexec: fix oops after TLB are invalidated
Sabyrzhan Tasbolatov (2):
net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
net/qrtr: restrict user-controlled length in qrtr_tun_write_iter()
Serge Semin (1):
usb: dwc3: ulpi: Replace CPU-based busyloop with Protocol-based one
Stefano Garzarella (2):
vsock/virtio: update credit only if socket is not closed
vsock: fix locking in vsock_shutdown()
Stefano Stabellini (1):
xen/arm: don't ignore return errors from set_phys_to_machine
Steven Rostedt (VMware) (2):
tracing: Do not count ftrace events in top level enable output
tracing: Check length before giving out the filter buffer
Sven Auhagen (1):
netfilter: flowtable: fix tcp and udp header checksum update
Victor Lu (2):
drm/amd/display: Fix dc_sink kref count in emulated_link_detect
drm/amd/display: Free atomic state after drm_atomic_commit
Makefile | 2 +-
arch/arm/boot/dts/lpc32xx.dtsi | 3 -
arch/arm/include/asm/kexec-internal.h | 12 ++++
arch/arm/kernel/asm-offsets.c | 5 ++
arch/arm/kernel/machine_kexec.c | 20 +++---
arch/arm/kernel/relocate_kernel.S | 38 +++--------
arch/arm/kernel/signal.c | 14 ++--
arch/arm/xen/enlighten.c | 2 -
arch/arm/xen/p2m.c | 6 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/h8300/kernel/asm-offsets.c | 3 +
arch/riscv/include/asm/page.h | 5 +-
arch/x86/Makefile | 6 +-
arch/x86/kvm/svm.c | 1 -
arch/x86/xen/p2m.c | 15 ++---
block/bfq-iosched.c | 8 +--
drivers/block/xen-blkback/blkback.c | 30 +++++----
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++--
drivers/i2c/busses/i2c-stm32f7.c | 11 ++-
.../net/ethernet/stmicro/stmmac/stmmac_tc.c | 7 +-
drivers/net/wireless/mediatek/mt76/dma.c | 8 ++-
drivers/net/xen-netback/netback.c | 4 +-
drivers/net/xen-netback/rx.c | 9 ++-
drivers/platform/x86/hp-wmi.c | 14 ++--
drivers/scsi/qla2xxx/qla_tmpl.c | 9 +--
drivers/scsi/qla2xxx/qla_tmpl.h | 2 +-
drivers/usb/dwc3/ulpi.c | 20 ++++--
drivers/xen/gntdev.c | 37 +++++-----
drivers/xen/xen-scsiback.c | 4 +-
drivers/xen/xenbus/xenbus.h | 1 -
drivers/xen/xenbus/xenbus_probe.c | 2 +-
fs/overlayfs/copy_up.c | 15 +++--
fs/overlayfs/inode.c | 2 +
fs/overlayfs/super.c | 13 ++--
include/asm-generic/vmlinux.lds.h | 2 +-
include/linux/netdevice.h | 2 +
include/xen/grant_table.h | 1 +
include/xen/xenbus.h | 2 -
kernel/bpf/stackmap.c | 2 +
kernel/trace/trace.c | 2 +-
kernel/trace/trace_events.c | 3 +-
net/netfilter/nf_conntrack_core.c | 3 +-
net/netfilter/nf_flow_table_core.c | 4 +-
net/netfilter/xt_recent.c | 12 +++-
net/qrtr/qrtr.c | 2 +-
net/qrtr/tun.c | 6 ++
net/rds/rdma.c | 3 +
net/sctp/proc.c | 16 +++--
net/vmw_vsock/af_vsock.c | 13 ++--
net/vmw_vsock/hyperv_transport.c | 4 --
net/vmw_vsock/virtio_transport_common.c | 4 +-
security/commoncap.c | 67 ++++++++++++-------
virt/kvm/kvm_main.c | 3 +-
53 files changed, 295 insertions(+), 204 deletions(-)
create mode 100644 arch/arm/include/asm/kexec-internal.h
--
2.25.1
1
50
From: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 34278
CVE: NA
-------------------------------------------------
Set dentry before goto error handling branch.
fs/resctrlfs.c: In function ‘resctrl_mount’:
fs/resctrlfs.c:419:9: warning: ‘dentry’ may be used uninitialized in this function [-Wmaybe-uninitialized]
return dentry;
^~~~~~
Fixes: 1b70f98921b10 ("arm64/mpam: resctrl: Use resctrl_group_init_alloc() for default group")
Signed-off-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/resctrlfs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c
index 190ad509714d5..df47b105609b9 100644
--- a/fs/resctrlfs.c
+++ b/fs/resctrlfs.c
@@ -351,8 +351,10 @@ static struct dentry *resctrl_mount(struct file_system_type *fs_type,
}
ret = resctrl_group_init_alloc(&resctrl_group_default);
- if (ret < 0)
+ if (ret < 0) {
+ dentry = ERR_PTR(ret);
goto out_schema;
+ }
ret = resctrl_group_create_info_dir(resctrl_group_default.kn, &kn_info);
if (ret) {
--
2.25.1
1
0
Cong Wang (1):
af_key: relax availability checks for skb size calculation
Dave Wysochanski (2):
SUNRPC: Move simple_get_bytes and simple_get_netobj into private
header
SUNRPC: Handle 0 length opaque XDR object data properly
David Collins (1):
regulator: core: avoid regulator_resolve_supply() race condition
Douglas Anderson (1):
regulator: core: Clean enabling always-on regulators + their supplies
Emmanuel Grumbach (1):
iwlwifi: pcie: add a NULL check in iwl_pcie_txq_unmap
Greg Kroah-Hartman (1):
Linux 4.19.176
Johannes Berg (3):
iwlwifi: mvm: take mutex for calling iwl_mvm_get_sync_time()
iwlwifi: pcie: fix context info memory leak
iwlwifi: mvm: guard against device removal in reprobe
Mark Brown (1):
regulator: Fix lockdep warning resolving supplies
Masami Hiramatsu (1):
tracing/kprobe: Fix to support kretprobe events on unloaded modules
Ming Lei (2):
block: don't hold q->sysfs_lock in elevator_init_mq
blk-mq: don't hold q->sysfs_lock in blk_mq_map_swqueue
Olliver Schinagl (1):
regulator: core: enable power when setting up constraints
Pan Bian (1):
chtls: Fix potential resource leak
Peter Gonda (1):
Fix unsynchronized access to sev members through
svm_register_enc_region
Phillip Lougher (3):
squashfs: add more sanity checks in id lookup
squashfs: add more sanity checks in inode lookup
squashfs: add more sanity checks in xattr id lookup
Sibi Sankar (2):
remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before
load
remoteproc: qcom_q6v5_mss: Validate MBA firmware size before load
Steven Rostedt (VMware) (1):
fgraph: Initialize tracing_graph_pause at task creation
Tobin C. Harding (1):
lib/string: Add strscpy_pad() function
Trond Myklebust (1):
pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()
Makefile | 2 +-
arch/x86/kvm/svm.c | 18 ++--
block/blk-mq.c | 7 --
block/elevator.c | 14 ++--
drivers/crypto/chelsio/chtls/chtls_cm.c | 7 +-
.../wireless/intel/iwlwifi/mvm/debugfs-vif.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +-
.../intel/iwlwifi/pcie/ctxt-info-gen3.c | 11 ++-
drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 5 ++
drivers/regulator/core.c | 84 +++++++++++++------
drivers/remoteproc/qcom_q6v5_pil.c | 11 ++-
fs/nfs/pnfs.c | 8 +-
fs/squashfs/export.c | 41 +++++++--
fs/squashfs/id.c | 40 +++++++--
fs/squashfs/squashfs_fs_sb.h | 1 +
fs/squashfs/super.c | 6 +-
fs/squashfs/xattr.h | 10 ++-
fs/squashfs/xattr_id.c | 66 +++++++++++++--
include/linux/kprobes.h | 2 +-
include/linux/string.h | 4 +
include/linux/sunrpc/xdr.h | 3 +-
init/init_task.c | 3 +-
kernel/kprobes.c | 34 ++++++--
kernel/trace/ftrace.c | 2 -
kernel/trace/trace_kprobe.c | 4 +-
lib/string.c | 47 +++++++++--
net/key/af_key.c | 6 +-
net/sunrpc/auth_gss/auth_gss.c | 30 +------
net/sunrpc/auth_gss/auth_gss_internal.h | 45 ++++++++++
net/sunrpc/auth_gss/gss_krb5_mech.c | 31 +------
30 files changed, 375 insertions(+), 173 deletions(-)
create mode 100644 net/sunrpc/auth_gss/auth_gss_internal.h
--
2.25.1
1
25
From: Chenguangli <chenguangli2(a)huawei.com>
driver inclusion
category: feature
bugzilla: NA
-----------------------------------------------------------------------
This module is used to register the hifc driver FC capability to the
SCSI layer.
Signed-off-by: Chenguangli <chenguangli2(a)huawei.com>
Reviewed-by: Zengweiliang <zengweiliang.zengweiliang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/huawei/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/huawei/Kconfig b/drivers/scsi/huawei/Kconfig
index a9fbdef9b4b38..1fe47e626f568 100644
--- a/drivers/scsi/huawei/Kconfig
+++ b/drivers/scsi/huawei/Kconfig
@@ -3,9 +3,10 @@
#
config SCSI_HUAWEI_FC
- tristate "Huawei devices"
+ tristate "Huawei Fibre Channel Adapter"
depends on PCI && SCSI
depends on SCSI_FC_ATTRS
+ depends on ARM64 || X86_64
default m
---help---
If you have a Fibre Channel PCI card belonging to this class, say Y.
--
2.25.1
1
4
Alexey Dobriyan (1):
Input: i8042 - unbreak Pegatron C15B
Arnd Bergmann (1):
elfcore: fix building with clang
Aurelien Aptel (1):
cifs: report error instead of invalid when revalidating a dentry fails
Benjamin Valentin (1):
Input: xpad - sync supported devices with fork on GitHub
Chenxin Jin (1):
USB: serial: cp210x: add new VID/PID for supporting Teraoka AD2000
Christoph Schemmel (1):
USB: serial: option: Adding support for Cinterion MV31
DENG Qingfang (1):
net: dsa: mv88e6xxx: override existent unicast portvec in port_fdb_add
Dan Carpenter (1):
USB: gadget: legacy: fix an error code in eth_bind()
Dave Hansen (1):
x86/apic: Add extra serialization for non-serializing MSRs
David Howells (1):
rxrpc: Fix deadlock around release of dst cached on udp tunnel
Felix Fietkau (1):
mac80211: fix station rate table updates on assoc
Fengnan Chang (1):
mmc: core: Limit retries when analyse of SDIO tuples fails
Gary Bisson (1):
usb: dwc3: fix clock issue during resume in OTG mode
Greg Kroah-Hartman (1):
Linux 4.19.175
Gustavo A. R. Silva (1):
smb3: Fix out-of-bounds bug in SMB2_negotiate()
Heiko Stuebner (1):
usb: dwc2: Fix endpoint direction check in ep_from_windex
Hugh Dickins (1):
mm: thp: fix MADV_REMOVE deadlock on shmem THP
Jeremy Figgins (1):
USB: usblp: don't call usb_set_interface if there's a single alt
Josh Poimboeuf (1):
x86/build: Disable CET instrumentation in the kernel
Liangyan (1):
ovl: fix dentry leak in ovl_get_redirect
Marc Zyngier (1):
genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is
set
Mathias Nyman (1):
xhci: fix bounce buffer usage for non-sg list case
Muchun Song (4):
mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
mm: hugetlb: fix a race between freeing and dissolving the page
mm: hugetlb: fix a race between isolating and freeing page
mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
Nadav Amit (1):
iommu/vt-d: Do not use flush-queue when caching-mode is on
Pho Tran (1):
USB: serial: cp210x: add pid/vid for WSDA-200-USB
Roman Gushchin (1):
memblock: do not start bottom-up allocations with kernel_end
Russell King (1):
ARM: footbridge: fix dc21285 PCI configuration accessors
Sean Christopherson (1):
KVM: SVM: Treat SVM as unsupported when running as an SEV guest
Stefan Chulski (1):
net: mvpp2: TCAM entry enable should be written after SRAM data
Thorsten Leemhuis (1):
nvme-pci: avoid the deepest sleep state on Kingston A2000 SSDs
Vadim Fedorenko (1):
net: ip_tunnel: fix mtu calculation
Wang ShaoBo (1):
kretprobe: Avoid re-registration of the same kretprobe earlier
Xiao Ni (1):
md: Set prev_flush_start and flush_bio in an atomic way
Xie He (1):
net: lapb: Copy the skb before sending a packet
Yoshihiro Shimoda (1):
usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
Zyta Szpak (1):
arm64: dts: ls1046a: fix dcfg address range
Makefile | 8 +--
arch/arm/mach-footbridge/dc21285.c | 12 ++---
.../arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 2 +-
arch/x86/Makefile | 3 ++
arch/x86/include/asm/apic.h | 10 ----
arch/x86/include/asm/barrier.h | 18 +++++++
arch/x86/kernel/apic/apic.c | 4 ++
arch/x86/kernel/apic/x2apic_cluster.c | 6 ++-
arch/x86/kernel/apic/x2apic_phys.c | 6 ++-
arch/x86/kvm/svm.c | 5 ++
drivers/input/joystick/xpad.c | 17 ++++++-
drivers/input/serio/i8042-x86ia64io.h | 2 +
drivers/iommu/intel-iommu.c | 6 +++
drivers/md/md.c | 2 +
drivers/mmc/core/sdio_cis.c | 6 +++
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++-
.../net/ethernet/marvell/mvpp2/mvpp2_prs.c | 10 ++--
drivers/nvme/host/pci.c | 2 +
drivers/usb/class/usblp.c | 19 ++++---
drivers/usb/dwc2/gadget.c | 8 +--
drivers/usb/dwc3/core.c | 2 +-
drivers/usb/gadget/legacy/ether.c | 4 +-
drivers/usb/host/xhci-ring.c | 31 +++++++-----
drivers/usb/renesas_usbhs/fifo.c | 1 +
drivers/usb/serial/cp210x.c | 2 +
drivers/usb/serial/option.c | 6 +++
fs/afs/main.c | 6 +--
fs/cifs/dir.c | 22 ++++++++-
fs/cifs/smb2pdu.h | 2 +-
fs/hugetlbfs/inode.c | 3 +-
fs/overlayfs/dir.c | 2 +-
include/linux/elfcore.h | 22 +++++++++
include/linux/hugetlb.h | 3 ++
include/linux/msi.h | 6 +++
kernel/Makefile | 1 -
kernel/elfcore.c | 26 ----------
kernel/irq/msi.c | 44 ++++++++---------
kernel/kprobes.c | 4 ++
mm/huge_memory.c | 37 ++++++++------
mm/hugetlb.c | 48 ++++++++++++++++--
mm/memblock.c | 49 +++----------------
net/ipv4/ip_tunnel.c | 16 +++---
net/lapb/lapb_out.c | 3 +-
net/mac80211/driver-ops.c | 5 +-
net/mac80211/rate.c | 3 +-
net/rxrpc/af_rxrpc.c | 6 +--
46 files changed, 307 insertions(+), 199 deletions(-)
delete mode 100644 kernel/elfcore.c
--
2.25.1
1
39
Re: [PATCH] kbuild fix: keep the original function in Makefile.lib for non-RPi
by Zheng Zengkai 08 Mar '21
by Zheng Zengkai 08 Mar '21
08 Mar '21
Hi Yafen,
> ---------------------- [WARNING] checkpatch ----------------------
>
> total: 0 errors, 1 warnings, 27 lines checked
>
> WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
> #84:
> /bin/sh: -c: line 0: `set -e; echo ' DTCO arch/arm64/boot/dts/overlays/act-led.dtbo'; mkdir -p arch/arm64/boot/dts/overlays/ ; gcc -E -Wp,-MMD,arch/arm64/boot/dts/overlays/.act-led.dtbo.d.pre.tmp -nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp arch/arm64/boot/dts/overlays/act-led-overlay.dts ; ./scripts/dtc/dtc -@ -H epapr -O dtb -o arch/arm64/boot/dts/overlays/act-led.dtbo -b 0 -i arch/arm64/boot/dts/overlays/ -Wno-interrupt_provider -Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-gpios_property -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-graph_child_address -Wno-simple_bus_reg -Wno-unique_unit_address -Wno-pci_device_reg -Wno-interrupts_property ifeq (y,y) -Wno-label_is_string -Wno-reg_format -Wno-pci_device_bus_num -Wno-i2c_bus_reg -Wno-spi_bus_reg -Wno-avoid_default_addr_size endif -d arch/arm64/boot/dts/overlays/.act-led.dtbo.d.dtc.tmp arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp ; cat ...; rm -f arch/arm64/boot/dts/overlays/.act-led.dtbo.d'
>
> total: 0 errors, 1 warnings, 27 lines checked
>
> NOTE: For some of the reported defects, checkpatch may be able to
> mechanically convert to the typical style using --fix or --fix-inplace.
>
> kbuild-fix-keep-the-original-function-in-Makefile.lib-for-non-RPi.patch has style problems, please review.
This patch has style problems, please review.
Thanks!
2
1
[PATCH] kbuild fix: keep the original function in Makefile.lib for non-RPi
by fangyafenqidai@163.com 08 Mar '21
by fangyafenqidai@163.com 08 Mar '21
08 Mar '21
From: Fang Yafen <yafen(a)iscas.ac.cn>
Fix the following compile error when using bcm2711_defconfig (for RPi).
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `set -e; echo ' DTCO arch/arm64/boot/dts/overlays/act-led.dtbo'; mkdir -p arch/arm64/boot/dts/overlays/ ; gcc -E -Wp,-MMD,arch/arm64/boot/dts/overlays/.act-led.dtbo.d.pre.tmp -nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp arch/arm64/boot/dts/overlays/act-led-overlay.dts ; ./scripts/dtc/dtc -@ -H epapr -O dtb -o arch/arm64/boot/dts/overlays/act-led.dtbo -b 0 -i arch/arm64/boot/dts/overlays/ -Wno-interrupt_provider -Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-gpios_property -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-graph_child_address -Wno-simple_bus_reg -Wno-unique_unit_address -Wno-pci_device_reg -Wno-interrupts_property ifeq (y,y) -Wno-label_is_string -Wno-reg_format -Wno-pci_device_bus_num -Wno-i2c_bus_reg -Wno-spi_bus_reg -Wno-avoid_default_addr_size endif -d arch/arm64/boot/dts/overlays/.act-led.dtbo.d.dtc.tmp arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp ; cat ...; rm -f arch/arm64/boot/dts/overlays/.act-led.dtbo.d'
make[2]: *** [scripts/Makefile.lib;363: arch/arm64/boot/dts/overlays/act-led.dtbo] Error 1
make[2]: *** Waiting for unfinished jobs....
Related patches:
ffa2d13ccc3 BCM2708: Add core Device Tree support
4894352ec98 kbuild: Silence unavoidable dtc overlay warnings
a4a4d07f0cf kbuild: keep the original function for non-RPi
Signed-off-by: Fang Yafen <yafen(a)iscas.ac.cn>
---
scripts/Makefile.lib | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index c23e3ae7ef40..a0e0e2543165 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -342,25 +342,25 @@ endef
$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_rule,dtc,yaml)
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
quiet_cmd_dtco = DTCO $@
cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -@ -H epapr -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-Wno-interrupts_property \
-ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y) \
-Wno-label_is_string \
-Wno-reg_format \
-Wno-pci_device_bus_num \
-Wno-i2c_bus_reg \
-Wno-spi_bus_reg \
-Wno-avoid_default_addr_size \
-endif \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtbo: $(src)/%-overlay.dts FORCE
$(call if_changed_dep,dtco)
+endif
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
--
2.23.0
1
0
[PATCH openEuler-21.03 v3 1/2] arm64: Add memmap parameter and register pmem
by zhuling8@huawei.com 08 Mar '21
by zhuling8@huawei.com 08 Mar '21
08 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
---
arch/arm64/Kconfig | 21 ++++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 +++++++++++++++++
arch/arm64/kernel/setup.c | 10 +++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 +++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137..326f26d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c..be996f3 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 0000000..16eaf70
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d3..84c71c8 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b343744..f22faea 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb3..ce4de75 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3..6f8dc92 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.9.5
1
1
08 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 21 +++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 10 ++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 ++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137ab..326f26d40 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c6d..be996f3c1 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d31a..84c71c88d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b3437440d..f22faea1a 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb38b..ce4de7526 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..6f8dc9242 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.19.1
3
4
各位好,
根据前期沟通,OSV、驱动兼容性SIG都对内核接口兼容性提出了诉求。根据前期
沟通的信息,以及收集的驱动接口使用情况,形成一份 20.03 LTS SP1 SP2 兼容
性 KABI 白名单初稿,请大家评审。
KABI (Kernel Application Binary Interface) 兼容,即内核与驱动的二进制兼容。
就是驱动不用重新编译,就可以在新内核上安装使用。如果驱动用到的接口都
是兼容的,那么驱动就可以不用重新编译就可以在新版本安装使用。上游社区
考虑到便于开发、和防止架构腐化,不考虑 KABI 的兼容性。业界的 KABI 兼容
都是由 Linux 发行版来做的,而且兼容的接口越多、维护时间越长,维护成本
也越高。
openEuler 通过多次与下游OSV和驱动团队交流,根据下游反馈的诉求,
openEuler 20.03 LTS SP1、SP2 版本,提供一定范围的 KABI 兼容能力,目的是
使常用的板卡驱动,在SP1、后续的 SP1 update 版本、SP2及SP2 update版本能
兼容。
kabi 兼容列表白名单的主要输入是驱动(ko),我们根据下游的反馈,收集到
部分常用驱动,作为兼容的目标,驱动列表如下。
ARM64 版本拟兼容的驱动(ko)列表
|amdgpu.ko bnx2.ko bnx2x.ko bnxt_en.ko bnxt_re.ko hclge.ko hclgevf.ko hifc.ko hinic.ko hnae3.ko hns3.ko i40e.ko ice.ko igb.ko ixgbe.ko ixgbevf.ko lpfc.ko megaraid_sas.ko mlx4_core.ko mlx4_ib.ko mlx5_core.ko mlx5_ib.ko mpt3sas.ko nouveau.ko nvme.ko qed.ko qede.ko qla2xxx.ko smartpqi.ko tg3.ko txgbe.ko |
X86 版本拟兼容的驱动(ko)列表
|amdgpu.ko bnx2.ko bnx2x.ko bnxt_en.ko bnxt_re.ko hifc.ko hinic.ko i40e.ko ice.ko igb.ko ixgbe.ko ixgbevf.ko lpfc.ko megaraid_sas.ko mlx4_core.ko mlx4_ib.ko mlx5_core.ko mlx5_ib.ko mpt3sas.ko nouveau.ko nvme.ko qed.ko qede.ko qla2xxx.ko smartpqi.ko tg3.ko txgbe.ko |
我们收集了上表中驱动使用到接口,形成了一份 kabi 白名单列表初稿,请大家评审。
重要的说明和提示:
1. 上述列表中多数驱动,还没有针对 openEuler SP1 的正式二进制版本,因此我们
根据开源的版本或相近的版本收集了相关 kabi 列表,可能与板卡厂商的最终发布
的版本存在少量差异。下游OSV或驱动团队如果发现有接口没在给出的列表中的,
可以在评审过程中提出来。
2. 如果有新增 KABI 兼容性的诉求,需要给出需要兼容的 kabi 接口名称,以及使用
到的驱动名称,以方便评估。
3. 评审反馈,可以在 issue 中反馈,https://gitee.com/openeuler/kernel/issues/I3ABVJ
也可以通过回复邮件反馈。
4. 收集评审反馈信息的时间为1周,截止到下周五(3月12日)下午17:00.
---
openEuler kernel SIG, 2021-3-6
---
附1:ARM64 平台 KABI 白名单列表初稿(1905个)
acpi_bus_get_device
acpi_check_dsm
acpi_dev_found
acpi_disabled
acpi_dma_configure
acpi_evaluate_dsm
acpi_evaluate_object
acpi_format_exception
acpi_gbl_FADT
acpi_get_devices
acpi_get_handle
acpi_get_name
acpi_get_table
acpi_gsi_to_irq
acpi_handle_printk
acpi_has_method
acpi_lid_open
acpi_os_map_memory
acpi_os_unmap_memory
acpi_register_gsi
acpi_unregister_gsi
add_timer
add_wait_queue
add_wait_queue_exclusive
admin_timeout
alloc_chrdev_region
alloc_cpu_rmap
__alloc_disk_node
alloc_etherdev_mqs
alloc_netdev_mqs
alloc_pages_current
__alloc_pages_nodemask
__alloc_percpu
__alloc_skb
__alloc_workqueue_key
__arch_clear_user
__arch_copy_from_user
__arch_copy_in_user
__arch_copy_to_user
arch_timer_read_counter
arch_wb_cache_pmem
arm64_const_caps_ready
arp_tbl
async_schedule
_atomic_dec_and_lock
atomic_notifier_call_chain
atomic_notifier_chain_register
atomic_notifier_chain_unregister
attribute_container_find_class_device
autoremove_wake_function
backlight_device_register
backlight_device_unregister
backlight_force_update
bdevname
bdev_read_only
bdget_disk
_bin2bcd
bio_add_page
bio_alloc_bioset
bio_clone_fast
bio_endio
bio_free_pages
bio_init
bio_put
bioset_exit
bioset_init
__bitmap_and
__bitmap_andnot
__bitmap_clear
__bitmap_complement
__bitmap_equal
bitmap_find_free_region
bitmap_find_next_zero_area_off
bitmap_free
__bitmap_intersects
__bitmap_or
__bitmap_parse
bitmap_parselist
bitmap_print_to_pagebuf
bitmap_release_region
__bitmap_set
__bitmap_weight
__bitmap_xor
bitmap_zalloc
bit_wait
blk_alloc_queue
blk_check_plugged
blk_cleanup_queue
blkdev_get_by_path
blkdev_issue_discard
blkdev_issue_write_same
blkdev_issue_zeroout
blkdev_put
blk_execute_rq
blk_execute_rq_nowait
blk_finish_plug
blk_get_queue
blk_get_request
blk_mq_alloc_tag_set
blk_mq_complete_request
blk_mq_end_request
blk_mq_free_request
blk_mq_free_tag_set
blk_mq_init_queue
blk_mq_map_queues
blk_mq_pci_map_queues
blk_mq_quiesce_queue
blk_mq_run_hw_queues
blk_mq_start_request
blk_mq_tagset_busy_iter
blk_mq_tag_to_rq
blk_mq_unique_tag
blk_mq_unquiesce_queue
blk_mq_update_nr_hw_queues
blk_put_queue
blk_put_request
blk_queue_bounce_limit
blk_queue_dma_alignment
blk_queue_flag_clear
blk_queue_flag_set
blk_queue_io_min
blk_queue_io_opt
blk_queue_logical_block_size
blk_queue_make_request
blk_queue_max_discard_sectors
blk_queue_max_hw_sectors
blk_queue_max_segments
blk_queue_max_segment_size
blk_queue_max_write_same_sectors
blk_queue_physical_block_size
blk_queue_rq_timeout
blk_queue_segment_boundary
blk_queue_split
blk_queue_stack_limits
blk_queue_update_dma_alignment
blk_queue_virt_boundary
blk_queue_write_cache
blk_rq_append_bio
blk_rq_count_integrity_sg
blk_rq_map_integrity_sg
blk_rq_map_kern
blk_rq_map_sg
blk_rq_map_user_iov
blk_rq_unmap_user
blk_set_stacking_limits
blk_start_plug
blk_status_to_errno
blk_verify_command
blocking_notifier_call_chain
blocking_notifier_chain_register
blocking_notifier_chain_unregister
bpf_prog_add
bpf_prog_inc
bpf_prog_put
bpf_trace_run1
bpf_trace_run2
bpf_trace_run3
bpf_trace_run5
bpf_warn_invalid_xdp_action
bsg_job_done
btree_destroy
btree_geo32
btree_geo64
btree_get_prev
btree_init
btree_insert
btree_last
btree_lookup
btree_remove
btree_update
build_skb
cache_line_size
call_netdevice_notifiers
call_rcu_sched
call_srcu
call_usermodehelper
cancel_delayed_work
cancel_delayed_work_sync
cancel_work_sync
capable
cdev_add
cdev_del
cdev_init
__chash_table_copy_in
__chash_table_copy_out
__check_object_size
__class_create
class_destroy
__class_register
class_unregister
_cleanup_srcu_struct
clk_get_rate
commit_creds
compat_alloc_user_space
complete
complete_all
complete_and_exit
completion_done
component_add
component_del
_cond_resched
console_lock
console_unlock
__const_udelay
consume_skb
cpu_bit_bitmap
cpufreq_quick_get
__cpuhp_remove_state
__cpuhp_setup_state
cpu_hwcap_keys
cpu_hwcaps
cpumask_local_spread
cpumask_next
cpumask_next_and
cpu_number
__cpu_online_mask
__cpu_possible_mask
__cpu_present_mask
cpus_read_lock
cpus_read_unlock
crc32c
crc32_le
crc8
crc8_populate_msb
crc_t10dif
crypto_ahash_digest
crypto_ahash_final
crypto_ahash_setkey
crypto_alloc_ahash
crypto_destroy_tfm
crypto_register_shash
crypto_unregister_shash
csum_ipv6_magic
csum_partial
csum_tcpudp_nofold
_ctype
dcb_getapp
dcb_ieee_delapp
dcb_ieee_getapp_mask
dcb_ieee_setapp
dcbnl_cee_notify
dcb_setapp
debugfs_create_atomic_t
debugfs_create_dir
debugfs_create_file
debugfs_create_symlink
debugfs_create_u16
debugfs_create_u32
debugfs_create_u64
debugfs_create_u8
debugfs_lookup
debugfs_remove
default_llseek
default_wake_function
__delay
delayed_work_timer_fn
del_gendisk
del_timer
del_timer_sync
destroy_workqueue
dev_add_pack
dev_addr_add
dev_addr_del
dev_base_lock
dev_close
dev_driver_string
_dev_err
__dev_get_by_index
dev_get_by_index
dev_get_by_index_rcu
dev_get_by_name
dev_get_iflink
dev_get_stats
device_add_disk
device_create
device_create_file
device_destroy
device_link_add
device_release_driver
device_remove_file
device_reprobe
device_set_wakeup_capable
device_set_wakeup_enable
_dev_info
__dev_kfree_skb_any
__dev_kfree_skb_irq
devlink_alloc
devlink_free
devlink_param_driverinit_value_get
devlink_param_driverinit_value_set
devlink_params_register
devlink_params_unregister
devlink_param_value_changed
devlink_port_attrs_set
devlink_port_register
devlink_port_type_clear
devlink_port_type_eth_set
devlink_port_type_ib_set
devlink_port_unregister
devlink_region_create
devlink_region_destroy
devlink_region_shapshot_id_get
devlink_region_snapshot_create
devlink_register
devlink_unregister
dev_mc_add
dev_mc_add_excl
dev_mc_del
devm_free_irq
devm_hwmon_device_register_with_groups
devm_ioremap
devm_iounmap
devm_kfree
devm_kmalloc
devm_kmemdup
devm_mdiobus_alloc_size
devm_request_threaded_irq
_dev_notice
dev_open
dev_printk
dev_queue_xmit
dev_remove_pack
dev_set_mac_address
dev_set_mtu
dev_set_promiscuity
dev_trans_start
dev_uc_add
dev_uc_add_excl
dev_uc_del
_dev_warn
disable_irq
disable_irq_nosync
dma_alloc_from_dev_coherent
dma_common_get_sgtable
dma_common_mmap
dma_fence_add_callback
dma_fence_array_create
dma_fence_context_alloc
dma_fence_free
dma_fence_get_status
dma_fence_init
dma_fence_release
dma_fence_signal
dma_fence_signal_locked
dma_fence_wait_any_timeout
dma_fence_wait_timeout
dma_get_required_mask
dmam_alloc_coherent
dmam_free_coherent
dma_pool_alloc
dma_pool_create
dma_pool_destroy
dma_pool_free
dma_release_from_dev_coherent
dmi_check_system
dmi_get_system_info
dmi_match
__do_once_done
__do_once_start
do_wait_intr
down
downgrade_write
down_interruptible
down_read
down_read_trylock
down_timeout
down_trylock
down_write
down_write_killable
down_write_trylock
dput
dql_completed
dql_reset
drain_workqueue
driver_create_file
driver_for_each_device
driver_remove_file
drm_add_edid_modes
drm_add_modes_noedid
drm_atomic_add_affected_connectors
drm_atomic_add_affected_planes
drm_atomic_commit
drm_atomic_get_connector_state
drm_atomic_get_crtc_state
drm_atomic_get_plane_state
drm_atomic_helper_check
drm_atomic_helper_check_modeset
drm_atomic_helper_check_planes
drm_atomic_helper_check_plane_state
drm_atomic_helper_cleanup_planes
drm_atomic_helper_commit
drm_atomic_helper_commit_cleanup_done
drm_atomic_helper_commit_hw_done
__drm_atomic_helper_connector_destroy_state
drm_atomic_helper_connector_destroy_state
__drm_atomic_helper_connector_duplicate_state
__drm_atomic_helper_connector_reset
__drm_atomic_helper_crtc_destroy_state
__drm_atomic_helper_crtc_duplicate_state
drm_atomic_helper_disable_plane
drm_atomic_helper_legacy_gamma_set
drm_atomic_helper_page_flip
__drm_atomic_helper_plane_destroy_state
drm_atomic_helper_plane_destroy_state
__drm_atomic_helper_plane_duplicate_state
drm_atomic_helper_prepare_planes
drm_atomic_helper_resume
drm_atomic_helper_set_config
drm_atomic_helper_setup_commit
drm_atomic_helper_shutdown
drm_atomic_helper_suspend
drm_atomic_helper_swap_state
drm_atomic_helper_update_legacy_modeset_state
drm_atomic_helper_update_plane
drm_atomic_helper_wait_for_dependencies
drm_atomic_helper_wait_for_fences
drm_atomic_helper_wait_for_flip_done
drm_atomic_state_alloc
drm_atomic_state_default_clear
drm_atomic_state_default_release
__drm_atomic_state_free
drm_atomic_state_init
drm_calc_vbltimestamp_from_scanoutpos
drm_color_lut_extract
drm_compat_ioctl
drm_connector_attach_encoder
drm_connector_cleanup
drm_connector_init
drm_connector_list_iter_begin
drm_connector_list_iter_end
drm_connector_list_iter_next
drm_connector_register
drm_connector_set_path_property
drm_connector_unregister
drm_connector_update_edid_property
drm_crtc_accurate_vblank_count
drm_crtc_add_crc_entry
drm_crtc_arm_vblank_event
drm_crtc_cleanup
__drm_crtc_commit_free
drm_crtc_enable_color_mgmt
drm_crtc_force_disable_all
drm_crtc_from_index
drm_crtc_handle_vblank
drm_crtc_helper_set_config
drm_crtc_helper_set_mode
drm_crtc_init
drm_crtc_init_with_planes
drm_crtc_send_vblank_event
drm_crtc_vblank_count
drm_crtc_vblank_get
drm_crtc_vblank_off
drm_crtc_vblank_on
drm_crtc_vblank_put
drm_cvt_mode
drm_dbg
drm_debugfs_create_files
drm_detect_hdmi_monitor
drm_detect_monitor_audio
drm_dev_alloc
drm_dev_put
drm_dev_register
drm_dev_unregister
drm_dp_atomic_find_vcpi_slots
drm_dp_atomic_release_vcpi_slots
drm_dp_aux_register
drm_dp_aux_unregister
drm_dp_bw_code_to_link_rate
drm_dp_calc_pbn_mode
drm_dp_channel_eq_ok
drm_dp_check_act_status
drm_dp_clock_recovery_ok
drm_dp_dpcd_read
drm_dp_dpcd_read_link_status
drm_dp_dpcd_write
drm_dp_find_vcpi_slots
drm_dp_get_adjust_request_pre_emphasis
drm_dp_get_adjust_request_voltage
drm_dp_link_rate_to_bw_code
drm_dp_link_train_channel_eq_delay
drm_dp_link_train_clock_recovery_delay
drm_dp_mst_allocate_vcpi
drm_dp_mst_deallocate_vcpi
drm_dp_mst_detect_port
drm_dp_mst_get_edid
drm_dp_mst_hpd_irq
drm_dp_mst_reset_vcpi_slots
drm_dp_mst_topology_mgr_destroy
drm_dp_mst_topology_mgr_init
drm_dp_mst_topology_mgr_resume
drm_dp_mst_topology_mgr_set_mst
drm_dp_mst_topology_mgr_suspend
drm_dp_update_payload_part1
drm_dp_update_payload_part2
drm_edid_header_is_valid
drm_edid_is_valid
drm_edid_to_sad
drm_edid_to_speaker_allocation
drm_encoder_cleanup
drm_encoder_init
drm_err
drm_fb_helper_add_one_connector
drm_fb_helper_alloc_fbi
drm_fb_helper_blank
drm_fb_helper_cfb_copyarea
drm_fb_helper_cfb_fillrect
drm_fb_helper_cfb_imageblit
drm_fb_helper_check_var
drm_fb_helper_debug_enter
drm_fb_helper_debug_leave
drm_fb_helper_fill_fix
drm_fb_helper_fill_var
drm_fb_helper_fini
drm_fb_helper_hotplug_event
drm_fb_helper_init
drm_fb_helper_initial_config
drm_fb_helper_ioctl
drm_fb_helper_lastclose
drm_fb_helper_output_poll_changed
drm_fb_helper_pan_display
drm_fb_helper_prepare
drm_fb_helper_remove_one_connector
drm_fb_helper_setcmap
drm_fb_helper_set_par
drm_fb_helper_set_suspend
drm_fb_helper_set_suspend_unlocked
drm_fb_helper_single_add_all_connectors
drm_fb_helper_unregister_fbi
drm_format_plane_cpp
drm_framebuffer_cleanup
drm_framebuffer_init
drm_framebuffer_unregister_private
drm_gem_dmabuf_kmap
drm_gem_dmabuf_kunmap
drm_gem_dmabuf_mmap
drm_gem_dmabuf_release
drm_gem_dmabuf_vmap
drm_gem_dmabuf_vunmap
drm_gem_fb_create_handle
drm_gem_fb_destroy
drm_gem_handle_create
drm_gem_handle_delete
drm_gem_map_attach
drm_gem_map_detach
drm_gem_map_dma_buf
drm_gem_object_init
drm_gem_object_lookup
drm_gem_object_put_unlocked
drm_gem_object_release
drm_gem_prime_export
drm_gem_prime_fd_to_handle
drm_gem_prime_handle_to_fd
drm_gem_prime_import
drm_gem_private_object_init
drm_gem_unmap_dma_buf
drm_get_edid
drm_get_edid_switcheroo
drm_get_format_name
drm_get_max_iomem
drm_global_item_ref
drm_global_item_unref
drm_handle_vblank
drm_hdmi_avi_infoframe_from_display_mode
drm_hdmi_vendor_infoframe_from_display_mode
drm_helper_connector_dpms
drm_helper_disable_unused_functions
drm_helper_hpd_irq_event
drm_helper_mode_fill_fb_struct
drm_helper_probe_single_connector_modes
drm_helper_resume_force_mode
drm_i2c_encoder_detect
drm_i2c_encoder_init
drm_i2c_encoder_mode_fixup
drm_i2c_encoder_restore
drm_i2c_encoder_save
drm_invalid_op
drm_ioctl
drm_irq_install
drm_irq_uninstall
drm_is_current_master
drm_kms_helper_hotplug_event
drm_kms_helper_is_poll_worker
drm_kms_helper_poll_disable
drm_kms_helper_poll_enable
drm_kms_helper_poll_fini
drm_kms_helper_poll_init
drm_match_cea_mode
drm_mm_init
drm_mm_insert_node_in_range
drm_mm_print
drm_mm_remove_node
drm_mm_takedown
drm_mode_config_cleanup
drm_mode_config_init
drm_mode_config_reset
drm_mode_copy
drm_mode_create_dvi_i_properties
drm_mode_create_scaling_mode_property
drm_mode_create_tv_properties
drm_mode_crtc_set_gamma_size
drm_mode_debug_printmodeline
drm_mode_destroy
drm_mode_duplicate
drm_mode_equal
drm_mode_get_hv_timing
drm_mode_is_420_only
drm_mode_legacy_fb_format
drm_mode_object_find
drm_mode_object_put
drm_mode_probed_add
drm_mode_set_crtcinfo
drm_modeset_lock
drm_modeset_lock_all
drm_modeset_lock_all_ctx
drm_mode_set_name
drm_modeset_unlock
drm_modeset_unlock_all
drm_mode_vrefresh
drm_object_attach_property
drm_object_property_set_value
drm_open
drm_plane_cleanup
drm_plane_create_alpha_property
drm_plane_create_color_properties
drm_plane_create_zpos_immutable_property
drm_plane_create_zpos_property
drm_plane_force_disable
drm_plane_init
drm_poll
drm_primary_helper_destroy
drm_primary_helper_funcs
drm_prime_gem_destroy
drm_prime_pages_to_sg
drm_prime_sg_to_page_addr_arrays
drm_printf
__drm_printfn_seq_file
drm_property_add_enum
drm_property_create
drm_property_create_enum
drm_property_create_range
__drm_puts_seq_file
drm_read
drm_release
drm_scdc_read
drm_scdc_write
drm_sched_dependency_optimized
drm_sched_entity_destroy
drm_sched_entity_fini
drm_sched_entity_flush
drm_sched_entity_init
drm_sched_entity_push_job
drm_sched_entity_set_rq
drm_sched_fini
drm_sched_hw_job_reset
drm_sched_init
drm_sched_job_init
drm_sched_job_recovery
drm_send_event_locked
drm_syncobj_create
drm_syncobj_find
drm_syncobj_find_fence
drm_syncobj_free
drm_syncobj_get_fd
drm_syncobj_get_handle
drm_syncobj_replace_fence
drm_universal_plane_init
drm_vblank_init
drm_vma_node_allow
drm_vma_node_is_allowed
drm_vma_node_revoke
dst_release
dummy_dma_ops
dump_stack
__dynamic_dev_dbg
__dynamic_netdev_dbg
__dynamic_pr_debug
elfcorehdr_addr
emergency_restart
enable_irq
errno_to_blk_status
ether_setup
eth_get_headlen
eth_platform_get_mac_address
ethtool_convert_legacy_u32_to_link_mode
ethtool_convert_link_mode_to_legacy_u32
ethtool_intersect_link_masks
ethtool_op_get_link
ethtool_op_get_ts_info
eth_type_trans
eth_validate_addr
eventfd_ctx_fdget
eventfd_ctx_put
eventfd_signal
event_triggers_call
fasync_helper
fc_attach_transport
fc_block_scsi_eh
fc_eh_timed_out
fc_get_event_number
fc_host_post_event
fc_host_post_vendor_event
fc_release_transport
fc_remote_port_add
fc_remote_port_delete
fc_remote_port_rolechg
fc_remove_host
fc_vport_create
fc_vport_terminate
fd_install
fget
filemap_fault
filp_close
filp_open
find_get_pid
find_last_bit
find_next_bit
find_next_zero_bit
find_pid_ns
find_vma
finish_wait
firmware_request_nowarn
fixed_size_llseek
flow_keys_dissector
flush_delayed_work
flush_signals
flush_work
flush_workqueue
force_sig
fortify_panic
fput
free_fib_info
free_irq
free_irq_cpu_rmap
free_netdev
__free_pages
free_pages
free_percpu
from_kgid
from_kuid
fs_bio_set
gcd
generate_random_uuid
generic_end_io_acct
generic_file_llseek
generic_handle_irq
generic_make_request
generic_start_io_acct
genlmsg_put
genl_register_family
genl_unregister_family
genphy_read_status
genphy_restart_aneg
get_device
__get_free_pages
get_gendisk
get_pid_task
get_random_bytes
__get_task_comm
get_task_mm
get_unused_fd_flags
get_user_pages
get_user_pages_remote
get_zeroed_page
gic_pmr_sync
groups_alloc
groups_free
handle_simple_irq
hdmi_avi_infoframe_pack
hdmi_infoframe_pack
hnae3_register_ae_algo
hnae3_register_ae_dev
hnae3_register_client
hnae3_set_client_init_flag
hnae3_unregister_ae_algo
hnae3_unregister_ae_dev
hnae3_unregister_client
hrtimer_cancel
hrtimer_forward
hrtimer_init
hrtimer_start_range_ns
hrtimer_try_to_cancel
__hw_addr_sync_dev
__hw_addr_unsync_dev
hwmon_device_register
hwmon_device_register_with_groups
hwmon_device_register_with_info
hwmon_device_unregister
i2c_add_adapter
i2c_bit_add_bus
i2c_bit_algo
i2c_del_adapter
i2c_new_device
i2c_smbus_read_byte_data
i2c_smbus_write_byte_data
i2c_transfer
i2c_unregister_device
__ib_alloc_cq
ib_alloc_device
ib_alloc_odp_umem
__ib_alloc_pd
__ib_alloc_xrcd
__ib_create_cq
ib_create_qp
ib_create_send_mad
ib_dealloc_device
ib_dealloc_pd
ib_dereg_mr
ib_destroy_cq
ib_destroy_qp
ib_dispatch_event
ib_find_cached_pkey
ib_free_cq
ib_free_send_mad
ib_get_cached_pkey
ib_get_eth_speed
ib_get_gids_from_rdma_hdr
ib_get_rdma_header_version
ib_modify_qp
ib_modify_qp_is_ok
ib_post_send_mad
ib_process_cq_direct
ib_query_pkey
ib_query_port
ib_query_qp
ib_register_device
ib_register_mad_agent
ib_sa_cancel_query
ib_sa_guid_info_rec_query
ib_sa_register_client
ib_sa_unregister_client
ib_sg_to_pages
ib_ud_header_init
ib_ud_header_pack
ib_ud_ip4_csum
ib_umem_copy_from
ib_umem_get
ib_umem_odp_map_dma_pages
ib_umem_odp_unmap_dma_pages
ib_umem_page_count
ib_umem_release
ib_unregister_device
ib_unregister_mad_agent
ib_uverbs_get_ucontext
ida_alloc_range
ida_destroy
ida_free
idr_alloc
idr_alloc_cyclic
idr_alloc_u32
idr_destroy
idr_find
idr_for_each
idr_get_next
idr_get_next_ul
idr_preload
idr_remove
idr_replace
in4_pton
in6_pton
in_egroup_p
__inet6_lookup_established
__inet_lookup_established
in_group_p
init_net
__init_rwsem
init_srcu_struct
init_task
init_timer_key
init_uts_ns
init_wait_entry
__init_waitqueue_head
interval_tree_insert
interval_tree_iter_first
interval_tree_iter_next
interval_tree_remove
int_to_scsilun
invalidate_partition
iomem_resource
iommu_get_domain_for_dev
iommu_iova_to_phys
iommu_map
iommu_unmap
__ioremap
ioremap_cache
io_schedule
io_schedule_timeout
__iounmap
__iowrite32_copy
__iowrite64_copy
ip6_dst_hoplimit
ip_compute_csum
ipmi_create_user
ipmi_destroy_user
ipmi_free_recv_msg
ipmi_poll_interface
ipmi_request_settime
ipmi_set_gets_events
ipmi_set_my_address
ipmi_smi_msg_received
ipmi_unregister_smi
ipmi_validate_addr
ip_route_output_flow
ip_send_check
__ipv6_addr_type
ipv6_ext_hdr
ipv6_find_hdr
ipv6_skip_exthdr
ipv6_stub
irq_cpu_rmap_add
irq_create_mapping
__irq_domain_add
irq_domain_remove
irq_find_mapping
irq_get_irq_data
irq_poll_complete
irq_poll_disable
irq_poll_enable
irq_poll_init
irq_poll_sched
irq_set_affinity_hint
irq_set_affinity_notifier
irq_set_chip_and_handler_name
irq_to_desc
is_acpi_device_node
jiffies
jiffies_64
jiffies_to_msecs
jiffies_to_timespec64
jiffies_to_usecs
kallsyms_lookup_name
kasprintf
kernel_recvmsg
kernel_sendmsg
kernel_setsockopt
kfree
kfree_call_rcu
kfree_const
kfree_skb
kgdb_active
kgdb_breakpoint
kill_fasync
kimage_voffset
__kmalloc
kmalloc_caches
__kmalloc_node
kmalloc_order_trace
kmem_cache_alloc
kmem_cache_alloc_node
kmem_cache_alloc_node_trace
kmem_cache_alloc_trace
kmem_cache_create
kmem_cache_create_usercopy
kmem_cache_destroy
kmem_cache_free
kmem_cache_shrink
kmemdup
kobject_add
kobject_create_and_add
kobject_del
kobject_get
kobject_init
kobject_init_and_add
kobject_put
kobject_set_name
kobject_uevent
kobject_uevent_env
krealloc
kset_create_and_add
kset_find_obj
kset_register
kset_unregister
ksize
kstrdup
kstrdup_const
kstrndup
kstrtobool
kstrtobool_from_user
kstrtoint
kstrtoint_from_user
kstrtoll
kstrtoll_from_user
kstrtou16
kstrtouint
kstrtouint_from_user
kstrtoul_from_user
kstrtoull
kstrtoull_from_user
kthread_bind
kthread_create_on_node
kthread_park
kthread_should_stop
kthread_stop
kthread_unpark
ktime_get
ktime_get_coarse_real_ts64
ktime_get_raw
ktime_get_raw_ts64
ktime_get_real_seconds
ktime_get_real_ts64
ktime_get_seconds
ktime_get_ts64
ktime_get_with_offset
kvasprintf
kvfree
kvmalloc_node
kzfree
led_classdev_resume
led_classdev_suspend
led_classdev_unregister
__list_add_valid
__list_del_entry_valid
llist_add_batch
__ll_sc_atomic64_add
__ll_sc_atomic64_add_return
__ll_sc_atomic64_andnot
__ll_sc_atomic64_fetch_add
__ll_sc_atomic64_fetch_andnot
__ll_sc_atomic64_fetch_andnot_release
__ll_sc_atomic64_fetch_or
__ll_sc_atomic64_fetch_or_acquire
__ll_sc_atomic64_fetch_xor
__ll_sc_atomic64_or
__ll_sc_atomic64_sub
__ll_sc_atomic64_sub_return
__ll_sc_atomic_add
__ll_sc_atomic_add_return
__ll_sc_atomic_add_return_acquire
__ll_sc_atomic_sub
__ll_sc_atomic_sub_return
__ll_sc_atomic_sub_return_release
__ll_sc___cmpxchg_case_acq_4
__ll_sc___cmpxchg_case_mb_4
__ll_sc___cmpxchg_case_mb_8
__local_bh_enable_ip
__lock_page
lock_page_memcg
lockref_get
lock_sock_nested
logic_inw
logic_outw
make_kgid
make_kuid
mark_page_accessed
match_strdup
match_string
match_token
_mcount
mdev_dev
mdev_from_dev
mdev_get_drvdata
mdev_parent_dev
mdev_register_device
mdev_register_driver
mdev_set_drvdata
mdev_unregister_device
mdev_unregister_driver
mdio45_probe
mdiobus_alloc_size
mdiobus_free
mdiobus_get_phy
mdiobus_read
__mdiobus_register
mdiobus_unregister
mdiobus_write
mdio_mii_ioctl
memchr
memchr_inv
memcmp
memcpy
__memcpy_fromio
__memcpy_toio
memdup_user
memdup_user_nul
memmove
memory_read_from_buffer
memparse
mempool_alloc
mempool_alloc_slab
mempool_create
mempool_create_node
mempool_destroy
mempool_free
mempool_free_slab
mempool_kfree
mempool_kmalloc
memscan
mem_section
memset
__memset_io
memstart_addr
memzero_explicit
metadata_dst_alloc
misc_deregister
misc_register
mlxfw_firmware_flash
mmput
__mmu_notifier_register
mmu_notifier_register
mmu_notifier_unregister
mmu_notifier_unregister_no_release
mod_delayed_work_on
mod_timer
mod_timer_pending
__module_get
module_layout
module_put
module_refcount
__msecs_to_jiffies
msleep
msleep_interruptible
__mutex_init
mutex_lock
mutex_lock_interruptible
mutex_lock_killable
mutex_trylock
mutex_unlock
__napi_alloc_skb
napi_complete_done
napi_consume_skb
napi_disable
napi_gro_flush
napi_gro_receive
napi_hash_del
__napi_schedule
__napi_schedule_irqoff
napi_schedule_prep
__ndelay
ndo_dflt_bridge_getlink
ndo_dflt_fdb_add
neigh_destroy
__neigh_event_send
neigh_lookup
netdev_alloc_frag
__netdev_alloc_skb
netdev_bind_sb_channel_queue
netdev_crit
netdev_err
netdev_features_change
netdev_info
netdev_lower_get_next
netdev_master_upper_dev_get
netdev_master_upper_dev_get_rcu
netdev_notice
netdev_printk
netdev_reset_tc
netdev_rss_key_fill
netdev_rx_handler_register
netdev_rx_handler_unregister
netdev_set_num_tc
netdev_set_sb_channel
netdev_set_tc_queue
netdev_unbind_sb_channel
netdev_update_features
netdev_walk_all_upper_dev_rcu
netdev_warn
netif_carrier_off
netif_carrier_on
netif_device_attach
netif_device_detach
netif_get_num_default_rss_queues
netif_napi_add
netif_napi_del
netif_receive_skb
netif_rx
netif_schedule_queue
netif_set_real_num_rx_queues
netif_set_real_num_tx_queues
netif_set_xps_queue
netif_tx_stop_all_queues
netif_tx_wake_queue
netlink_ack
netlink_broadcast
__netlink_kernel_create
netlink_kernel_release
netlink_unicast
net_ratelimit
nla_find
nla_parse
nla_put
__nlmsg_put
node_data
__node_distance
node_states
node_to_cpumask_map
no_llseek
noop_llseek
nr_cpu_ids
nr_node_ids
nsecs_to_jiffies
ns_to_timespec
ns_to_timespec64
ns_to_timeval
numa_node
nvme_alloc_request
nvme_cancel_request
nvme_change_ctrl_state
nvme_cleanup_cmd
nvme_complete_async_event
nvme_complete_rq
nvme_disable_ctrl
nvme_enable_ctrl
nvme_fc_register_localport
nvme_fc_register_remoteport
nvme_fc_set_remoteport_devloss
nvme_fc_unregister_localport
nvme_fc_unregister_remoteport
nvme_init_ctrl
nvme_init_identify
nvme_io_timeout
nvme_kill_queues
nvme_remove_namespaces
nvme_reset_ctrl
nvme_reset_ctrl_sync
nvme_set_queue_count
nvme_setup_cmd
nvme_shutdown_ctrl
nvme_start_ctrl
nvme_start_freeze
nvme_start_queues
nvme_stop_ctrl
nvme_stop_queues
nvme_submit_sync_cmd
nvmet_fc_rcv_fcp_abort
nvmet_fc_rcv_fcp_req
nvmet_fc_rcv_ls_req
nvmet_fc_register_targetport
nvmet_fc_unregister_targetport
nvme_unfreeze
nvme_uninit_ctrl
nvme_wait_freeze
nvme_wait_freeze_timeout
nvme_wq
of_led_classdev_register
on_each_cpu
orderly_poweroff
out_of_line_wait_on_bit
override_creds
__page_file_index
__page_frag_cache_drain
page_frag_free
__page_mapcount
page_mapped
page_pool_alloc_pages
page_pool_create
page_pool_destroy
__page_pool_put_page
pagevec_lookup_range
pagevec_lookup_range_tag
__pagevec_release
panic
panic_notifier_list
param_array_ops
param_get_int
param_ops_bool
param_ops_byte
param_ops_charp
param_ops_int
param_ops_long
param_ops_short
param_ops_string
param_ops_uint
param_ops_ullong
param_ops_ulong
param_ops_ushort
param_set_bool
param_set_int
pci_alloc_irq_vectors_affinity
pci_assign_unassigned_bus_resources
pcibios_resource_to_bus
pci_bus_read_config_dword
pci_bus_resource_n
pci_bus_type
pci_cfg_access_lock
pci_cfg_access_unlock
pci_check_and_mask_intx
pci_choose_state
pci_cleanup_aer_uncorrect_error_status
pci_clear_master
pci_clear_mwi
pci_d3cold_disable
pci_dev_driver
pci_dev_get
pci_device_is_present
pci_dev_present
pci_dev_put
pci_disable_device
pci_disable_link_state
pci_disable_msi
pci_disable_msix
pci_disable_pcie_error_reporting
pci_disable_rom
pci_disable_sriov
pcie_bandwidth_available
pcie_capability_clear_and_set_word
pcie_capability_read_dword
pcie_capability_read_word
pcie_capability_write_word
pcie_flr
pcie_get_speed_cap
pcie_get_width_cap
pci_enable_atomic_ops_to_root
pci_enable_device
pci_enable_device_mem
pci_enable_msi
pci_enable_msix_range
pci_enable_pcie_error_reporting
pci_enable_rom
pci_enable_sriov
pci_enable_wake
pcie_print_link_status
pcie_relaxed_ordering_enabled
pcie_set_readrq
pci_find_capability
pci_find_ext_capability
pci_free_irq
pci_free_irq_vectors
pci_get_class
pci_get_device
pci_get_domain_bus_and_slot
pci_get_slot
pci_ignore_hotplug
pci_intx
pci_iomap
pci_ioremap_bar
pci_irq_get_affinity
pci_irq_vector
pci_map_rom
pci_match_id
pcim_enable_device
pcim_iomap
pcim_iomap_regions
pcim_iomap_table
pcim_iounmap
pci_msi_mask_irq
pci_msi_unmask_irq
pci_num_vf
pci_platform_rom
pci_prepare_to_sleep
pci_read_config_byte
pci_read_config_dword
pci_read_config_word
pci_read_vpd
__pci_register_driver
pci_release_regions
pci_release_resource
pci_release_selected_regions
pci_request_irq
pci_request_regions
pci_request_selected_regions
pci_rescan_bus
pci_resize_resource
pci_restore_state
pci_save_state
pci_select_bars
pci_set_master
pci_set_mwi
pci_set_power_state
pci_sriov_configure_simple
pci_sriov_get_totalvfs
pci_sriov_set_totalvfs
pci_stop_and_remove_bus_device
pci_stop_and_remove_bus_device_locked
pci_try_set_mwi
pci_unmap_rom
pci_unregister_driver
pci_vfs_assigned
pci_vpd_find_info_keyword
pci_vpd_find_tag
pci_wait_for_pending_transaction
pci_wake_from_d3
pci_write_config_byte
pci_write_config_dword
pci_write_config_word
pcix_set_mmrbc
PDE_DATA
__per_cpu_offset
perf_trace_buf_alloc
perf_trace_run_bpf_submit
pfn_valid
phy_attached_info
phy_connect
phy_connect_direct
phy_disconnect
phy_ethtool_ksettings_get
phy_ethtool_ksettings_set
phy_loopback
phy_mii_ioctl
phy_resume
phy_start
phy_start_aneg
phy_stop
phy_suspend
pid_task
pid_vnr
pm_power_off
pm_runtime_allow
__pm_runtime_disable
pm_runtime_enable
pm_runtime_forbid
__pm_runtime_idle
__pm_runtime_resume
pm_runtime_set_autosuspend_delay
__pm_runtime_set_status
__pm_runtime_suspend
__pm_runtime_use_autosuspend
pm_schedule_suspend
power_supply_is_system_supplied
prandom_bytes
prandom_u32
prepare_creds
prepare_to_wait
prepare_to_wait_event
prepare_to_wait_exclusive
print_hex_dump
printk
__printk_ratelimit
print_stack_trace
proc_create_data
proc_mkdir
__pskb_copy_fclone
pskb_expand_head
__pskb_pull_tail
___pskb_trim
ptp_clock_event
ptp_clock_index
ptp_clock_register
ptp_clock_unregister
ptp_find_pin
__put_cred
put_device
put_disk
__put_page
__put_task_struct
put_unused_fd
qed_get_eth_ops
qed_put_eth_ops
queue_delayed_work_on
queued_read_lock_slowpath
queued_spin_lock_slowpath
queued_write_lock_slowpath
queue_work_on
radix_tree_delete
radix_tree_gang_lookup
__radix_tree_insert
radix_tree_lookup
radix_tree_tagged
raid_class_attach
raid_class_release
___ratelimit
raw_notifier_call_chain
raw_notifier_chain_register
raw_notifier_chain_unregister
rb_erase
__rb_erase_color
rb_first
rb_first_postorder
__rb_insert_augmented
rb_insert_color
rb_next
rb_next_postorder
rb_replace_node
rbt_ib_umem_for_each_in_range
rbt_ib_umem_lookup
rcu_barrier
rdma_create_ah
rdma_destroy_ah
rdma_is_zero_gid
rdma_port_get_link_layer
rdma_query_ah
rdma_query_gid
rdma_restrack_get
rdma_restrack_put
rdma_roce_rescan_device
read_cache_pages
recalc_sigpending
refcount_dec_and_mutex_lock
refcount_dec_and_test_checked
refcount_dec_checked
refcount_inc_checked
refcount_inc_not_zero_checked
register_acpi_notifier
register_blkdev
__register_chrdev
register_chrdev_region
register_fib_notifier
register_inet6addr_notifier
register_inetaddr_notifier
register_netdev
register_netdevice_notifier
register_netevent_notifier
register_reboot_notifier
release_firmware
release_pages
__release_region
release_sock
remap_pfn_range
remove_conflicting_framebuffers
remove_proc_entry
remove_wait_queue
request_firmware
request_firmware_direct
request_firmware_nowait
__request_module
__request_region
request_threaded_irq
reservation_object_add_excl_fence
reservation_object_add_shared_fence
reservation_object_get_fences_rcu
reservation_object_reserve_shared
reservation_object_wait_timeout_rcu
reservation_ww_class
reset_devices
revert_creds
rhashtable_destroy
rhashtable_free_and_destroy
rhashtable_init
rhashtable_insert_slow
rhashtable_walk_enter
rhashtable_walk_exit
rhashtable_walk_next
rhashtable_walk_start_check
rhashtable_walk_stop
rhltable_init
rht_bucket_nested
rht_bucket_nested_insert
round_jiffies
round_jiffies_relative
rps_may_expire_flow
rtc_time64_to_tm
rtnl_is_locked
rtnl_lock
rtnl_trylock
rtnl_unlock
sas_attach_transport
sas_disable_tlr
sas_enable_tlr
sas_end_device_alloc
sas_expander_alloc
sas_is_tlr_enabled
sas_phy_add
sas_phy_alloc
sas_phy_free
sas_port_add
sas_port_add_phy
sas_port_alloc_num
sas_port_delete
sas_port_delete_phy
sas_port_free
sas_read_port_mode_page
sas_release_transport
sas_remove_host
sas_rphy_add
save_stack_trace
save_stack_trace_tsk
sbitmap_queue_clear
__sbitmap_queue_get
sched_clock
sched_setscheduler
schedule
schedule_hrtimeout
schedule_hrtimeout_range
schedule_timeout
schedule_timeout_interruptible
schedule_timeout_uninterruptible
scmd_printk
scnprintf
scsi_add_device
scsi_add_host_with_dma
scsi_block_requests
scsi_build_sense_buffer
scsi_change_queue_depth
scsi_device_get
scsi_device_lookup
scsi_device_put
scsi_device_set_state
scsi_device_type
scsi_dma_map
scsi_dma_unmap
__scsi_execute
scsi_get_vpd_page
scsi_host_alloc
scsi_host_busy
scsi_host_get
scsi_host_lookup
scsi_host_put
scsi_internal_device_block_nowait
scsi_internal_device_unblock_nowait
scsi_is_fc_rport
scsi_is_host_device
scsi_is_sdev_device
__scsi_iterate_devices
scsilun_to_int
scsi_normalize_sense
scsi_print_command
scsi_register_driver
scsi_remove_device
scsi_remove_host
scsi_remove_target
scsi_sanitize_inquiry_string
scsi_scan_host
scsi_unblock_requests
sdev_prefix_printk
secpath_dup
security_d_instantiate
send_sig
seq_lseek
seq_open
seq_printf
seq_putc
seq_puts
seq_read
seq_release
seq_write
set_cpus_allowed_ptr
set_current_groups
set_device_ro
set_disk_ro
set_freezable
set_normalized_timespec64
set_page_dirty
set_page_dirty_lock
set_user_nice
sg_alloc_table_from_pages
sg_copy_from_buffer
sg_copy_to_buffer
sg_free_table
sg_init_table
sg_miter_next
sg_miter_start
sg_miter_stop
sg_next
sigprocmask
si_meminfo
simple_attr_open
simple_attr_read
simple_attr_release
simple_attr_write
simple_open
simple_read_from_buffer
simple_strtol
simple_strtoul
simple_strtoull
simple_write_to_buffer
single_open
single_release
skb_add_rx_frag
skb_checksum
skb_checksum_help
skb_clone
skb_clone_tx_timestamp
skb_copy
skb_copy_bits
skb_copy_expand
skb_dequeue
__skb_flow_dissect
__skb_get_hash
__skb_gso_segment
skb_gso_validate_mac_len
__skb_pad
skb_pull
skb_push
skb_put
skb_queue_purge
skb_queue_tail
skb_realloc_headroom
skb_store_bits
skb_trim
skb_tstamp_tx
skb_vlan_pop
sk_free
smp_call_function_many
smp_call_function_single
snprintf
sock_create_kern
sock_edemux
sock_queue_err_skb
sock_release
softnet_data
sort
sprintf
srcu_barrier
__srcu_read_lock
__srcu_read_unlock
sscanf
__stack_chk_fail
__stack_chk_guard
starget_for_each_device
strcasecmp
strcat
strchr
strcmp
strcpy
strcspn
strim
strlcat
strlcpy
strlen
strncasecmp
strncat
strncmp
strncpy
strncpy_from_user
strnlen
strnstr
strpbrk
strrchr
strsep
strspn
strstr
submit_bio
__sw_hweight32
__sw_hweight64
__sw_hweight8
swiotlb_nr_tbl
switchdev_port_same_parent_id
__symbol_put
sync_file_create
synchronize_irq
synchronize_net
synchronize_sched
synchronize_srcu
sysfs_add_file_to_group
sysfs_create_bin_file
sysfs_create_file_ns
sysfs_create_group
sysfs_remove_bin_file
sysfs_remove_file_from_group
sysfs_remove_file_ns
sysfs_remove_group
sysfs_streq
system_state
system_unbound_wq
system_wq
sys_tz
task_active_pid_ns
tasklet_init
tasklet_kill
__tasklet_schedule
__task_pid_nr_ns
tcf_block_cb_register
tcf_block_cb_unregister
tcp_gro_complete
tcp_hashinfo
tc_setup_cb_egdev_register
tc_setup_cb_egdev_unregister
time64_to_tm
timecounter_cyc2time
timecounter_init
timecounter_read
tls_get_record
tls_validate_xmit_skb
to_drm_sched_fence
trace_define_field
trace_event_buffer_commit
trace_event_buffer_reserve
trace_event_ignore_this_pid
trace_event_raw_init
trace_event_reg
trace_handle_return
__tracepoint_dma_fence_emit
__tracepoint_xdp_exception
trace_print_array_seq
trace_print_flags_seq
trace_raw_output_prep
trace_seq_printf
trace_seq_putc
try_module_get
try_wait_for_completion
ttm_bo_add_to_lru
ttm_bo_clean_mm
ttm_bo_del_sub_from_lru
ttm_bo_device_init
ttm_bo_device_release
ttm_bo_dma_acc_size
ttm_bo_eviction_valuable
ttm_bo_evict_mm
ttm_bo_global_init
ttm_bo_global_release
ttm_bo_init
ttm_bo_init_mm
ttm_bo_init_reserved
ttm_bo_kmap
ttm_bo_kunmap
ttm_bo_lock_delayed_workqueue
ttm_bo_manager_func
ttm_bo_mem_put
ttm_bo_mem_space
ttm_bo_mmap
ttm_bo_move_accel_cleanup
ttm_bo_move_memcpy
ttm_bo_move_to_lru_tail
ttm_bo_move_ttm
ttm_bo_pipeline_move
ttm_bo_put
ttm_bo_unlock_delayed_workqueue
ttm_bo_validate
ttm_bo_wait
ttm_dma_page_alloc_debugfs
ttm_dma_populate
ttm_dma_tt_fini
ttm_dma_tt_init
ttm_dma_unpopulate
ttm_eu_backoff_reservation
ttm_eu_fence_buffer_objects
ttm_eu_reserve_buffers
ttm_fbdev_mmap
ttm_mem_global_init
ttm_mem_global_release
ttm_page_alloc_debugfs
ttm_pool_populate
ttm_pool_unpopulate
ttm_populate_and_map_pages
ttm_sg_tt_init
ttm_tt_bind
ttm_tt_set_placement_caching
ttm_unmap_and_unpopulate_pages
__udelay
udp4_hwcsum
uio_event_notify
__uio_register_device
uio_unregister_device
unlock_page
unlock_page_memcg
unmap_mapping_range
unregister_acpi_notifier
unregister_blkdev
__unregister_chrdev
unregister_chrdev_region
unregister_fib_notifier
unregister_inet6addr_notifier
unregister_inetaddr_notifier
unregister_netdev
unregister_netdevice_notifier
unregister_netevent_notifier
unregister_reboot_notifier
unuse_mm
up
up_read
up_write
__usecs_to_jiffies
use_mm
usleep_range
_uverbs_alloc
uverbs_copy_to
uverbs_destroy_def_handler
uverbs_fd_class
uverbs_get_flags32
uverbs_get_flags64
uverbs_idr_class
vfree
vga_client_register
vlan_dev_real_dev
vlan_dev_vlan_id
vlan_dev_vlan_proto
vmalloc
__vmalloc
vmalloc_node
vmalloc_to_page
vmap
vm_insert_page
vm_mmap
vm_munmap
vprintk
vscnprintf
vsnprintf
vsprintf
vunmap
vzalloc
vzalloc_node
wait_for_completion
wait_for_completion_interruptible
wait_for_completion_interruptible_timeout
wait_for_completion_io_timeout
wait_for_completion_killable
wait_for_completion_timeout
wait_on_page_bit
__wake_up
wake_up_bit
__wake_up_locked
wake_up_process
__warn_printk
work_busy
write_cache_pages
ww_mutex_lock
ww_mutex_lock_interruptible
ww_mutex_unlock
xdp_do_flush_map
xdp_do_redirect
xdp_return_frame
xdp_return_frame_rx_napi
xdp_rxq_info_is_reg
xdp_rxq_info_reg
xdp_rxq_info_reg_mem_model
xdp_rxq_info_unreg
xdp_rxq_info_unused
xfrm_replay_seqhi
xz_dec_end
xz_dec_init
xz_dec_run
yield
zap_vma_ptes
zlib_inflate
zlib_inflateEnd
zlib_inflateInit2
zlib_inflate_workspacesize
附2:x86 平台 KABI 白名单列表初稿(2228个)
acpi_bus_get_device
acpi_bus_register_driver
acpi_bus_unregister_driver
acpi_check_dsm
acpi_dev_found
acpi_disabled
acpi_dma_configure
acpi_evaluate_dsm
acpi_evaluate_integer
acpi_evaluate_object
acpi_format_exception
acpi_gbl_FADT
acpi_get_devices
acpi_get_handle
acpi_get_name
acpi_get_table
acpi_gsi_to_irq
acpi_handle_printk
acpi_has_method
acpi_install_notify_handler
acpi_lid_open
acpi_os_map_memory
acpi_os_unmap_memory
acpi_register_gsi
acpi_remove_notify_handler
acpi_unregister_gsi
acpi_video_get_edid
acpi_walk_namespace
address_space_init_once
add_timer
add_wait_queue
add_wait_queue_exclusive
admin_timeout
alloc_chrdev_region
alloc_cpumask_var
alloc_cpu_rmap
__alloc_disk_node
alloc_etherdev_mqs
alloc_netdev_mqs
alloc_pages_current
__alloc_pages_nodemask
__alloc_percpu
__alloc_skb
__alloc_workqueue_key
anon_inode_getfile
apic
arch_dma_alloc_attrs
arch_io_free_memtype_wc
arch_io_reserve_memtype_wc
arch_phys_wc_add
arch_phys_wc_del
arch_wb_cache_pmem
arp_tbl
async_schedule
_atomic_dec_and_lock
atomic_notifier_call_chain
atomic_notifier_chain_register
atomic_notifier_chain_unregister
attribute_container_find_class_device
autoremove_wake_function
backlight_device_register
backlight_device_unregister
backlight_force_update
bdevname
bdev_read_only
bdget_disk
_bin2bcd
bio_add_page
bio_alloc_bioset
bio_clone_fast
bio_endio
bio_free_pages
bio_init
bio_put
bioset_exit
bioset_init
__bitmap_and
__bitmap_andnot
__bitmap_clear
__bitmap_complement
__bitmap_equal
bitmap_find_free_region
bitmap_find_next_zero_area_off
__bitmap_intersects
__bitmap_or
__bitmap_parse
bitmap_parselist
bitmap_print_to_pagebuf
bitmap_release_region
__bitmap_set
__bitmap_shift_left
__bitmap_shift_right
__bitmap_subset
__bitmap_weight
__bitmap_xor
bitmap_zalloc
bit_wait
blk_alloc_queue
blk_check_plugged
blk_cleanup_queue
blkdev_get_by_path
blkdev_issue_discard
blkdev_issue_write_same
blkdev_issue_zeroout
blkdev_put
blk_execute_rq
blk_execute_rq_nowait
blk_finish_plug
blk_get_queue
blk_get_request
blk_init_tags
blk_mq_alloc_tag_set
blk_mq_complete_request
blk_mq_end_request
blk_mq_free_request
blk_mq_free_tag_set
blk_mq_init_queue
blk_mq_map_queues
blk_mq_pci_map_queues
blk_mq_quiesce_queue
blk_mq_run_hw_queues
blk_mq_start_request
blk_mq_tagset_busy_iter
blk_mq_tag_to_rq
blk_mq_unique_tag
blk_mq_unquiesce_queue
blk_mq_update_nr_hw_queues
blk_put_queue
blk_put_request
blk_queue_bounce_limit
blk_queue_dma_alignment
blk_queue_flag_clear
blk_queue_flag_set
blk_queue_free_tags
blk_queue_init_tags
blk_queue_io_min
blk_queue_io_opt
blk_queue_logical_block_size
blk_queue_make_request
blk_queue_max_discard_sectors
blk_queue_max_hw_sectors
blk_queue_max_segments
blk_queue_max_segment_size
blk_queue_max_write_same_sectors
blk_queue_physical_block_size
blk_queue_rq_timeout
blk_queue_segment_boundary
blk_queue_split
blk_queue_stack_limits
blk_queue_update_dma_alignment
blk_queue_virt_boundary
blk_queue_write_cache
blk_rq_append_bio
blk_rq_count_integrity_sg
blk_rq_map_integrity_sg
blk_rq_map_kern
blk_rq_map_sg
blk_rq_map_user_iov
blk_rq_unmap_user
blk_set_stacking_limits
blk_start_plug
blk_status_to_errno
blk_verify_command
blocking_notifier_call_chain
blocking_notifier_chain_register
blocking_notifier_chain_unregister
boot_cpu_data
bpf_prog_add
bpf_prog_inc
bpf_prog_put
bpf_trace_run1
bpf_trace_run2
bpf_trace_run3
bpf_trace_run5
bpf_warn_invalid_xdp_action
bsg_job_done
btree_destroy
btree_geo32
btree_geo64
btree_get_prev
btree_init
btree_insert
btree_last
btree_lookup
btree_remove
btree_update
build_skb
bus_find_device_by_name
__cachemode2pte_tbl
call_netdevice_notifiers
call_rcu_sched
call_usermodehelper
cancel_delayed_work
cancel_delayed_work_sync
cancel_work_sync
capable
cdev_add
cdev_del
cdev_device_add
cdev_device_del
cdev_init
__chash_table_copy_in
__chash_table_copy_out
__check_object_size
__class_create
class_create_file_ns
class_destroy
__class_register
class_remove_file_ns
class_unregister
_cleanup_srcu_struct
clear_user
clk_get_rate
cm_class
cnic_register_driver
cnic_unregister_driver
commit_creds
compat_alloc_user_space
complete
complete_all
complete_and_exit
completion_done
component_add
component_del
_cond_resched
configfs_register_subsystem
configfs_remove_default_groups
configfs_unregister_subsystem
config_group_init
config_group_init_type_name
config_item_put
console_lock
console_unlock
__const_udelay
consume_skb
_copy_from_user
_copy_to_user
copy_user_enhanced_fast_string
copy_user_generic_string
copy_user_generic_unrolled
cpu_bit_bitmap
cpu_core_map
cpufreq_get
cpufreq_quick_get
__cpuhp_remove_state
__cpuhp_setup_state
cpu_info
cpu_khz
cpumask_local_spread
cpumask_next
cpumask_next_and
cpu_number
__cpu_online_mask
__cpu_possible_mask
__cpu_present_mask
cpu_sibling_map
cpus_read_lock
cpus_read_unlock
crc32c
crc32_le
crc8
crc8_populate_msb
crc_t10dif
crypto_ahash_digest
crypto_ahash_final
crypto_ahash_setkey
crypto_alloc_ahash
crypto_destroy_tfm
crypto_register_shash
crypto_unregister_shash
csum_ipv6_magic
csum_partial
_ctype
current_task
dca3_get_tag
dca_add_requester
dca_register_notify
dca_remove_requester
dca_unregister_notify
dcb_getapp
dcb_ieee_delapp
dcb_ieee_getapp_mask
dcb_ieee_setapp
dcbnl_cee_notify
dcbnl_ieee_notify
dcb_setapp
debugfs_create_atomic_t
debugfs_create_dir
debugfs_create_file
debugfs_create_u32
debugfs_create_u64
debugfs_create_u8
debugfs_lookup
debugfs_remove
__default_kernel_pte_mask
default_llseek
default_wake_function
__delay
delayed_work_timer_fn
del_gendisk
del_timer
del_timer_sync
destroy_workqueue
dev_add_pack
dev_addr_add
dev_addr_del
dev_base_lock
dev_close
dev_driver_string
_dev_err
__dev_get_by_index
dev_get_by_index
dev_get_by_index_rcu
dev_get_by_name
dev_get_iflink
dev_get_stats
device_add_disk
device_create
device_create_file
device_destroy
device_initialize
device_link_add
device_release_driver
device_remove_file
device_reprobe
device_set_wakeup_capable
device_set_wakeup_enable
_dev_info
__dev_kfree_skb_any
__dev_kfree_skb_irq
devlink_alloc
devlink_free
devlink_param_driverinit_value_get
devlink_param_driverinit_value_set
devlink_params_register
devlink_params_unregister
devlink_param_value_changed
devlink_port_attrs_set
devlink_port_register
devlink_port_type_clear
devlink_port_type_ib_set
devlink_port_unregister
devlink_region_create
devlink_region_destroy
devlink_region_shapshot_id_get
devlink_region_snapshot_create
devlink_register
devlink_unregister
devmap_managed_key
dev_mc_add
dev_mc_add_excl
dev_mc_del
devm_free_irq
devm_hwmon_device_register_with_groups
devm_ioremap
devm_iounmap
devm_kfree
devm_kmalloc
devm_kmemdup
devm_request_threaded_irq
_dev_notice
dev_printk
dev_queue_xmit
__dev_remove_pack
dev_remove_pack
dev_set_mac_address
dev_set_mtu
dev_set_name
dev_set_promiscuity
dev_trans_start
dev_uc_add
dev_uc_add_excl
dev_uc_del
_dev_warn
disable_irq
disable_irq_nosync
dma_fence_add_callback
dma_fence_array_create
dma_fence_context_alloc
dma_fence_free
dma_fence_get_status
dma_fence_init
dma_fence_release
dma_fence_signal
dma_fence_signal_locked
dma_fence_wait_any_timeout
dma_fence_wait_timeout
dma_get_required_mask
dmam_alloc_coherent
dmam_free_coherent
dma_ops
dma_pool_alloc
dma_pool_create
dma_pool_destroy
dma_pool_free
dmi_check_system
dmi_get_system_info
dmi_match
__do_once_done
__do_once_start
do_wait_intr
down
downgrade_write
down_interruptible
down_read
down_read_trylock
down_timeout
down_trylock
down_write
down_write_killable
down_write_trylock
dput
dql_completed
dql_reset
drain_workqueue
driver_create_file
driver_for_each_device
driver_remove_file
drm_add_edid_modes
drm_add_modes_noedid
drm_atomic_add_affected_connectors
drm_atomic_add_affected_planes
drm_atomic_commit
drm_atomic_get_connector_state
drm_atomic_get_crtc_state
drm_atomic_get_plane_state
drm_atomic_helper_check
drm_atomic_helper_check_modeset
drm_atomic_helper_check_planes
drm_atomic_helper_check_plane_state
drm_atomic_helper_cleanup_planes
drm_atomic_helper_commit
drm_atomic_helper_commit_cleanup_done
drm_atomic_helper_commit_hw_done
__drm_atomic_helper_connector_destroy_state
drm_atomic_helper_connector_destroy_state
__drm_atomic_helper_connector_duplicate_state
__drm_atomic_helper_connector_reset
__drm_atomic_helper_crtc_destroy_state
__drm_atomic_helper_crtc_duplicate_state
drm_atomic_helper_disable_plane
drm_atomic_helper_legacy_gamma_set
drm_atomic_helper_page_flip
__drm_atomic_helper_plane_destroy_state
drm_atomic_helper_plane_destroy_state
__drm_atomic_helper_plane_duplicate_state
drm_atomic_helper_prepare_planes
drm_atomic_helper_resume
drm_atomic_helper_set_config
drm_atomic_helper_setup_commit
drm_atomic_helper_shutdown
drm_atomic_helper_suspend
drm_atomic_helper_swap_state
drm_atomic_helper_update_legacy_modeset_state
drm_atomic_helper_update_plane
drm_atomic_helper_wait_for_dependencies
drm_atomic_helper_wait_for_fences
drm_atomic_helper_wait_for_flip_done
drm_atomic_state_alloc
drm_atomic_state_default_clear
drm_atomic_state_default_release
__drm_atomic_state_free
drm_atomic_state_init
drm_calc_vbltimestamp_from_scanoutpos
drm_color_lut_extract
drm_compat_ioctl
drm_connector_attach_encoder
drm_connector_cleanup
drm_connector_init
drm_connector_list_iter_begin
drm_connector_list_iter_end
drm_connector_list_iter_next
drm_connector_register
drm_connector_set_path_property
drm_connector_unregister
drm_connector_update_edid_property
drm_crtc_accurate_vblank_count
drm_crtc_add_crc_entry
drm_crtc_arm_vblank_event
drm_crtc_cleanup
__drm_crtc_commit_free
drm_crtc_enable_color_mgmt
drm_crtc_force_disable_all
drm_crtc_from_index
drm_crtc_handle_vblank
drm_crtc_helper_set_config
drm_crtc_helper_set_mode
drm_crtc_init
drm_crtc_init_with_planes
drm_crtc_send_vblank_event
drm_crtc_vblank_count
drm_crtc_vblank_get
drm_crtc_vblank_off
drm_crtc_vblank_on
drm_crtc_vblank_put
drm_cvt_mode
drm_dbg
drm_debug
drm_debugfs_create_files
drm_detect_hdmi_monitor
drm_detect_monitor_audio
drm_dev_alloc
drm_dev_put
drm_dev_register
drm_dev_unref
drm_dev_unregister
drm_dp_atomic_find_vcpi_slots
drm_dp_atomic_release_vcpi_slots
drm_dp_aux_register
drm_dp_aux_unregister
drm_dp_bw_code_to_link_rate
drm_dp_calc_pbn_mode
drm_dp_channel_eq_ok
drm_dp_check_act_status
drm_dp_clock_recovery_ok
drm_dp_dpcd_read
drm_dp_dpcd_read_link_status
drm_dp_dpcd_write
drm_dp_find_vcpi_slots
drm_dp_get_adjust_request_pre_emphasis
drm_dp_get_adjust_request_voltage
drm_dp_link_rate_to_bw_code
drm_dp_link_train_channel_eq_delay
drm_dp_link_train_clock_recovery_delay
drm_dp_mst_allocate_vcpi
drm_dp_mst_deallocate_vcpi
drm_dp_mst_detect_port
drm_dp_mst_get_edid
drm_dp_mst_hpd_irq
drm_dp_mst_reset_vcpi_slots
drm_dp_mst_topology_mgr_destroy
drm_dp_mst_topology_mgr_init
drm_dp_mst_topology_mgr_resume
drm_dp_mst_topology_mgr_set_mst
drm_dp_mst_topology_mgr_suspend
drm_dp_update_payload_part1
drm_dp_update_payload_part2
drm_edid_header_is_valid
drm_edid_is_valid
drm_edid_to_sad
drm_edid_to_speaker_allocation
drm_encoder_cleanup
drm_encoder_init
drm_err
drm_fb_helper_add_one_connector
drm_fb_helper_alloc_fbi
drm_fb_helper_blank
drm_fb_helper_cfb_copyarea
drm_fb_helper_cfb_fillrect
drm_fb_helper_cfb_imageblit
drm_fb_helper_check_var
drm_fb_helper_debug_enter
drm_fb_helper_debug_leave
drm_fb_helper_fill_fix
drm_fb_helper_fill_var
drm_fb_helper_fini
drm_fb_helper_hotplug_event
drm_fb_helper_init
drm_fb_helper_initial_config
drm_fb_helper_ioctl
drm_fb_helper_lastclose
drm_fb_helper_output_poll_changed
drm_fb_helper_pan_display
drm_fb_helper_prepare
drm_fb_helper_remove_one_connector
drm_fb_helper_setcmap
drm_fb_helper_set_par
drm_fb_helper_set_suspend
drm_fb_helper_set_suspend_unlocked
drm_fb_helper_single_add_all_connectors
drm_fb_helper_unregister_fbi
drm_format_plane_cpp
drm_framebuffer_cleanup
drm_framebuffer_init
drm_framebuffer_unregister_private
drm_gem_dmabuf_kmap
drm_gem_dmabuf_kunmap
drm_gem_dmabuf_mmap
drm_gem_dmabuf_release
drm_gem_dmabuf_vmap
drm_gem_dmabuf_vunmap
drm_gem_fb_create_handle
drm_gem_fb_destroy
drm_gem_handle_create
drm_gem_handle_delete
drm_gem_map_attach
drm_gem_map_detach
drm_gem_map_dma_buf
drm_gem_object_free
drm_gem_object_init
drm_gem_object_lookup
drm_gem_object_put_unlocked
drm_gem_object_release
drm_gem_prime_export
drm_gem_prime_fd_to_handle
drm_gem_prime_handle_to_fd
drm_gem_prime_import
drm_gem_private_object_init
drm_gem_unmap_dma_buf
drm_get_edid
drm_get_edid_switcheroo
drm_get_format_name
drm_get_max_iomem
drm_global_item_ref
drm_global_item_unref
drm_handle_vblank
drm_hdmi_avi_infoframe_from_display_mode
drm_hdmi_vendor_infoframe_from_display_mode
drm_helper_connector_dpms
drm_helper_disable_unused_functions
drm_helper_hpd_irq_event
drm_helper_mode_fill_fb_struct
drm_helper_probe_single_connector_modes
drm_helper_resume_force_mode
drm_i2c_encoder_detect
drm_i2c_encoder_init
drm_i2c_encoder_mode_fixup
drm_i2c_encoder_restore
drm_i2c_encoder_save
drm_invalid_op
drm_ioctl
drm_irq_install
drm_irq_uninstall
drm_is_current_master
drm_kms_helper_hotplug_event
drm_kms_helper_is_poll_worker
drm_kms_helper_poll_disable
drm_kms_helper_poll_enable
drm_kms_helper_poll_fini
drm_kms_helper_poll_init
drm_match_cea_mode
drm_mm_init
drm_mm_insert_node_in_range
drm_mm_print
drm_mm_remove_node
drm_mm_takedown
drm_mode_config_cleanup
drm_mode_config_init
drm_mode_config_reset
drm_mode_copy
drm_mode_create_dvi_i_properties
drm_mode_create_scaling_mode_property
drm_mode_create_tv_properties
drm_mode_crtc_set_gamma_size
drm_mode_debug_printmodeline
drm_mode_destroy
drm_mode_duplicate
drm_mode_equal
drm_mode_get_hv_timing
drm_mode_is_420_only
drm_mode_legacy_fb_format
drm_mode_object_find
drm_mode_object_put
drm_mode_probed_add
drm_mode_set_crtcinfo
drm_modeset_lock
drm_modeset_lock_all
drm_modeset_lock_all_ctx
drm_mode_set_name
drm_modeset_unlock
drm_modeset_unlock_all
drm_mode_vrefresh
drm_object_attach_property
drm_object_property_set_value
drm_open
drm_plane_cleanup
drm_plane_create_alpha_property
drm_plane_create_color_properties
drm_plane_create_zpos_immutable_property
drm_plane_create_zpos_property
drm_plane_force_disable
drm_plane_init
drm_poll
drm_primary_helper_destroy
drm_primary_helper_funcs
drm_prime_gem_destroy
drm_prime_pages_to_sg
drm_prime_sg_to_page_addr_arrays
drm_printf
__drm_printfn_seq_file
drm_property_add_enum
drm_property_create
drm_property_create_enum
drm_property_create_range
__drm_puts_seq_file
drm_read
drm_release
drm_scdc_read
drm_scdc_write
drm_sched_dependency_optimized
drm_sched_entity_destroy
drm_sched_entity_fini
drm_sched_entity_flush
drm_sched_entity_init
drm_sched_entity_push_job
drm_sched_entity_set_rq
drm_sched_fini
drm_sched_hw_job_reset
drm_sched_init
drm_sched_job_init
drm_sched_job_recovery
drm_send_event_locked
drm_syncobj_create
drm_syncobj_find
drm_syncobj_find_fence
drm_syncobj_free
drm_syncobj_get_fd
drm_syncobj_get_handle
drm_syncobj_replace_fence
drm_universal_plane_init
drm_vblank_init
drm_vma_node_allow
drm_vma_node_is_allowed
drm_vma_node_revoke
dst_release
dump_stack
__dynamic_dev_dbg
__dynamic_netdev_dbg
__dynamic_pr_debug
efi
elfcorehdr_addr
emergency_restart
empty_zero_page
enable_irq
errno_to_blk_status
ether_setup
eth_get_headlen
eth_platform_get_mac_address
ethtool_convert_legacy_u32_to_link_mode
ethtool_convert_link_mode_to_legacy_u32
__ethtool_get_link_ksettings
ethtool_intersect_link_masks
ethtool_op_get_link
ethtool_op_get_ts_info
eth_type_trans
eth_validate_addr
event_triggers_call
ex_handler_default
ex_handler_refcount
fasync_helper
fc_attach_transport
fc_block_scsi_eh
fc_disc_config
fc_disc_init
fc_eh_host_reset
fc_eh_timed_out
fc_elsct_init
fc_elsct_send
fc_exch_init
fc_exch_mgr_alloc
fc_exch_mgr_free
fc_exch_mgr_list_clone
fc_exch_recv
fc_fabric_login
fc_fabric_logoff
_fc_frame_alloc
fc_frame_alloc_fill
fc_get_event_number
fc_get_host_port_state
fc_get_host_speed
fc_get_host_stats
fc_host_post_event
fc_host_post_vendor_event
fc_lport_bsg_request
fc_lport_config
fc_lport_destroy
fc_lport_flogi_resp
fc_lport_init
fc_lport_logo_resp
fc_lport_reset
fcoe_check_wait_queue
fcoe_clean_pending_queue
fcoe_ctlr_destroy
fcoe_ctlr_device_add
fcoe_ctlr_device_delete
fcoe_ctlr_els_send
fcoe_ctlr_get_lesb
fcoe_ctlr_init
fcoe_ctlr_link_down
fcoe_ctlr_link_up
fcoe_ctlr_recv
fcoe_ctlr_recv_flogi
fcoe_fc_crc
fcoe_fcf_get_selected
fcoe_get_lesb
fcoe_get_paged_crc_eof
fcoe_get_wwn
fcoe_link_speed_update
fcoe_queue_timer
fcoe_start_io
fcoe_transport_attach
fcoe_transport_detach
fcoe_validate_vport_create
fcoe_wwn_from_mac
fcoe_wwn_to_str
fc_release_transport
fc_remote_port_add
fc_remote_port_delete
fc_remote_port_rolechg
fc_remove_host
fc_rport_terminate_io
fc_set_mfs
fc_set_rport_loss_tmo
fc_slave_alloc
fc_vport_create
fc_vport_id_lookup
fc_vport_setlink
fc_vport_terminate
__fdget
fd_install
__fentry__
fget
__fib_lookup
fib_table_lookup
filemap_fault
filp_close
filp_open
find_first_bit
find_first_zero_bit
find_get_pid
find_last_bit
find_next_bit
find_next_zero_bit
find_pid_ns
find_vma
finish_wait
firmware_request_nowarn
fixed_size_llseek
flow_keys_dissector
flush_delayed_work
flush_signals
flush_work
flush_workqueue
follow_pfn
force_sig
fortify_panic
fput
free_cpumask_var
free_fib_info
free_irq
free_irq_cpu_rmap
free_netdev
__free_pages
free_pages
free_percpu
from_kgid
from_kuid
fs_bio_set
gcd
generate_random_uuid
generic_end_io_acct
generic_handle_irq
generic_make_request
generic_start_io_acct
genlmsg_put
genl_register_family
genl_unregister_family
get_device
__get_free_pages
get_gendisk
get_pid_task
get_random_bytes
__get_task_comm
get_task_mm
get_task_pid
get_unused_fd_flags
__get_user_2
__get_user_4
__get_user_8
get_user_pages
get_user_pages_remote
get_zeroed_page
groups_alloc
groups_free
handle_simple_irq
hdmi_avi_infoframe_pack
hdmi_infoframe_pack
hrtimer_cancel
hrtimer_forward
hrtimer_init
hrtimer_start_range_ns
hrtimer_try_to_cancel
__hw_addr_sync_dev
__hw_addr_unsync_dev
hwmon_device_register
hwmon_device_register_with_groups
hwmon_device_register_with_info
hwmon_device_unregister
i2c_add_adapter
i2c_bit_add_bus
i2c_bit_algo
i2c_del_adapter
i2c_new_device
i2c_smbus_read_byte_data
i2c_smbus_write_byte_data
i2c_transfer
i2c_unregister_device
__ib_alloc_cq
ib_alloc_device
ib_alloc_odp_umem
__ib_alloc_pd
ib_attach_mcast
ib_cache_gid_parse_type_str
ib_cache_gid_type_str
ib_cancel_mad
ib_cm_init_qp_attr
ib_cm_insert_listen
ib_cm_listen
ib_cm_notify
ibcm_reject_msg
ib_copy_path_rec_from_user
ib_copy_path_rec_to_user
ib_copy_qp_attr_to_user
ib_create_ah_from_wc
ib_create_cm_id
__ib_create_cq
ib_create_qp
ib_create_qp_security
ib_create_send_mad
ib_dealloc_device
ib_dealloc_pd
ib_dealloc_xrcd
ib_destroy_cm_id
ib_destroy_cq
ib_destroy_qp
ib_destroy_rwq_ind_table
ib_destroy_wq
ib_detach_mcast
ib_dispatch_event
ib_find_cached_pkey
ib_free_cq
ib_free_recv_mad
ib_free_send_mad
ib_get_cached_pkey
ib_get_cached_port_state
ib_get_eth_speed
ib_get_gids_from_rdma_hdr
ib_get_mad_data_offset
ib_get_net_dev_by_params
ib_get_rdma_header_version
ib_get_rmpp_segment
ib_init_ah_attr_from_path
ib_init_ah_attr_from_wc
ib_init_ah_from_mcmember
ib_is_mad_class_rmpp
ib_mad_kernel_rmpp_agent
ib_modify_mad
ib_modify_port
ib_modify_qp
ib_modify_qp_is_ok
ib_modify_qp_with_udata
ibnl_put_attr
ibnl_put_msg
ib_open_qp
ib_post_send_mad
ib_process_cq_direct
ib_query_pkey
ib_query_port
ib_query_qp
ib_query_srq
ib_rdmacg_try_charge
ib_rdmacg_uncharge
ib_register_client
ib_register_device
ib_register_event_handler
ib_register_mad_agent
ib_response_mad
ib_sa_cancel_query
ib_sa_free_multicast
ib_sa_get_mcmember_rec
ib_sa_guid_info_rec_query
ib_sa_join_multicast
ib_sa_path_rec_get
ib_sa_register_client
ib_sa_sendonly_fullmem_support
ib_sa_unregister_client
ib_send_cm_apr
ib_send_cm_drep
ib_send_cm_dreq
ib_send_cm_lap
ib_send_cm_mra
ib_send_cm_rej
ib_send_cm_rep
ib_send_cm_req
ib_send_cm_rtu
ib_send_cm_sidr_rep
ib_send_cm_sidr_req
ib_set_client_data
ib_sg_to_pages
ib_ud_header_init
ib_ud_header_pack
ib_ud_ip4_csum
ib_umem_copy_from
ib_umem_get
ib_umem_odp_map_dma_pages
ib_umem_odp_unmap_dma_pages
ib_umem_page_count
ib_umem_release
ib_unregister_client
ib_unregister_device
ib_unregister_event_handler
ib_unregister_mad_agent
ib_uverbs_get_ucontext
ib_wc_status_msg
ida_alloc_range
ida_destroy
ida_free
idr_alloc
idr_alloc_cyclic
idr_alloc_u32
idr_destroy
idr_find
idr_for_each
idr_get_next
idr_get_next_ul
idr_preload
idr_remove
idr_replace
igrab
in6_dev_finish_destroy
in_dev_finish_destroy
in_egroup_p
__inet6_lookup_established
inet_get_local_port_range
__inet_lookup_established
in_group_p
init_net
__init_rwsem
init_srcu_struct
init_task
init_timer_key
init_uts_ns
init_wait_entry
__init_waitqueue_head
interval_tree_insert
interval_tree_iter_first
interval_tree_iter_next
interval_tree_remove
int_to_scsilun
invalidate_partition
iomem_resource
iommu_get_domain_for_dev
iommu_iova_to_phys
iommu_map
iommu_unmap
ioread16
ioread16be
ioread32
ioread32be
ioread8
ioremap_cache
ioremap_nocache
ioremap_wc
io_schedule
io_schedule_timeout
iounmap
iowrite16
iowrite32
iowrite32be
__iowrite32_copy
__iowrite64_copy
iowrite8
ip6_dst_hoplimit
ip_compute_csum
ip_mc_dec_group
ip_mc_inc_group
ipmi_create_user
ipmi_destroy_user
ipmi_free_recv_msg
ipmi_poll_interface
ipmi_request_settime
ipmi_set_gets_events
ipmi_set_my_address
ipmi_smi_msg_received
ipmi_unregister_smi
ipmi_validate_addr
ip_route_output_flow
ip_send_check
ip_tos2prio
iput
__ipv6_addr_type
ipv6_ext_hdr
ipv6_find_hdr
ipv6_skip_exthdr
ipv6_stub
irq_cpu_rmap_add
irq_create_mapping
__irq_domain_add
irq_domain_remove
irq_find_mapping
irq_modify_status
irq_poll_complete
irq_poll_disable
irq_poll_enable
irq_poll_init
irq_poll_sched
irq_set_affinity_hint
irq_set_affinity_notifier
irq_set_chip_and_handler_name
irq_to_desc
is_acpi_device_node
iscsi_boot_create_ethernet
iscsi_boot_create_host_kset
iscsi_boot_create_initiator
iscsi_boot_create_target
iscsi_boot_destroy_kset
__iscsi_complete_pdu
iscsi_complete_scsi_task
iscsi_conn_bind
iscsi_conn_failure
iscsi_conn_get_param
iscsi_conn_send_pdu
iscsi_conn_setup
iscsi_conn_start
iscsi_conn_stop
iscsi_conn_teardown
iscsi_create_endpoint
iscsi_create_iface
iscsi_destroy_endpoint
iscsi_destroy_iface
iscsi_eh_abort
iscsi_eh_device_reset
iscsi_eh_recover_target
iscsi_eh_session_reset
iscsi_get_port_speed_name
iscsi_get_port_state_name
__iscsi_get_task
iscsi_host_add
iscsi_host_alloc
iscsi_host_for_each_session
iscsi_host_free
iscsi_host_get_param
iscsi_host_remove
iscsi_itt_to_task
iscsi_lookup_endpoint
iscsi_offload_mesg
__iscsi_put_task
iscsi_put_task
iscsi_queuecommand
iscsi_register_transport
iscsi_session_failure
iscsi_session_get_param
iscsi_session_recovery_timedout
iscsi_session_setup
iscsi_session_teardown
iscsi_set_param
iscsi_suspend_queue
iscsi_target_alloc
iscsi_unregister_transport
is_uv_system
iw_cm_accept
iw_cm_connect
iw_cm_disconnect
iw_cm_init_qp_attr
iw_cm_listen
iw_cm_reject
iwcm_reject_msg
iw_create_cm_id
iw_destroy_cm_id
jiffies
jiffies_64
jiffies_to_msecs
jiffies_to_timespec64
jiffies_to_usecs
kallsyms_lookup_name
kasprintf
kernel_fpu_begin
kernel_fpu_end
kernel_recvmsg
kernel_sendmsg
kernel_setsockopt
kfree
kfree_call_rcu
kfree_const
kfree_skb
kgdb_active
kgdb_breakpoint
kill_fasync
__kmalloc
kmalloc_caches
__kmalloc_node
kmalloc_order_trace
kmem_cache_alloc
kmem_cache_alloc_node
kmem_cache_alloc_node_trace
kmem_cache_alloc_trace
kmem_cache_create
kmem_cache_create_usercopy
kmem_cache_destroy
kmem_cache_free
kmem_cache_shrink
kmemdup
kobject_add
kobject_create_and_add
kobject_del
kobject_get
kobject_init
kobject_init_and_add
kobject_put
kobject_set_name
kobject_uevent
kobject_uevent_env
krealloc
kset_create_and_add
kset_find_obj
kset_register
kset_unregister
ksize
kstrdup
kstrdup_const
kstrndup
kstrtobool
kstrtobool_from_user
kstrtoint
kstrtoint_from_user
kstrtoll
kstrtoll_from_user
kstrtou16
kstrtou8
kstrtouint
kstrtouint_from_user
kstrtoul_from_user
kstrtoull
kstrtoull_from_user
kthread_bind
kthread_create_on_node
kthread_park
kthread_should_stop
kthread_stop
kthread_unpark
ktime_get
ktime_get_coarse_real_ts64
ktime_get_raw
ktime_get_raw_ts64
ktime_get_real_seconds
ktime_get_real_ts64
ktime_get_seconds
ktime_get_ts64
ktime_get_with_offset
kvasprintf
kvfree
kvmalloc_node
kzfree
led_classdev_resume
led_classdev_suspend
led_classdev_unregister
libfc_vport_create
__list_add_valid
__list_del_entry_valid
llist_add_batch
__local_bh_enable_ip
__lock_page
lock_page_memcg
lockref_get
lock_sock_nested
make_kgid
make_kuid
mark_page_accessed
match_strdup
match_string
match_token
mdio45_probe
mdiobus_alloc_size
mdiobus_free
mdiobus_get_phy
__mdiobus_register
mdiobus_unregister
mdio_mii_ioctl
memchr
memchr_inv
memcmp
memcpy
memdup_user
memdup_user_nul
memmove
memory_read_from_buffer
memparse
mempool_alloc
mempool_alloc_slab
mempool_create
mempool_create_node
mempool_destroy
mempool_free
mempool_free_slab
mempool_kfree
mempool_kmalloc
memscan
mem_section
memset
memzero_explicit
metadata_dst_alloc
mfd_add_devices
mfd_remove_devices
misc_deregister
misc_register
mlxfw_firmware_flash
__mmdrop
mmput
__mmu_notifier_register
mmu_notifier_register
mmu_notifier_unregister
mmu_notifier_unregister_no_release
mod_delayed_work_on
mod_timer
mod_timer_pending
__module_get
module_layout
module_put
module_refcount
__msecs_to_jiffies
msleep
msleep_interruptible
__mutex_init
mutex_lock
mutex_lock_interruptible
mutex_lock_killable
mutex_trylock
mutex_unlock
mxm_wmi_call_mxds
mxm_wmi_call_mxmx
mxm_wmi_supported
__napi_alloc_skb
napi_complete_done
napi_consume_skb
napi_disable
napi_get_frags
napi_gro_flush
napi_gro_frags
napi_gro_receive
napi_hash_del
__napi_schedule
__napi_schedule_irqoff
napi_schedule_prep
__ndelay
ndo_dflt_bridge_getlink
ndo_dflt_fdb_add
nd_tbl
neigh_destroy
__neigh_event_send
neigh_lookup
netdev_alloc_frag
__netdev_alloc_skb
netdev_bind_sb_channel_queue
netdev_crit
netdev_err
netdev_features_change
netdev_info
netdev_lower_get_next
netdev_master_upper_dev_get
netdev_master_upper_dev_get_rcu
netdev_notice
netdev_printk
netdev_reset_tc
netdev_rss_key_fill
netdev_rx_handler_register
netdev_rx_handler_unregister
netdev_set_num_tc
netdev_set_sb_channel
netdev_set_tc_queue
netdev_unbind_sb_channel
netdev_update_features
netdev_walk_all_upper_dev_rcu
netdev_warn
netif_carrier_off
netif_carrier_on
netif_device_attach
netif_device_detach
netif_get_num_default_rss_queues
netif_napi_add
netif_napi_del
netif_receive_skb
netif_rx
netif_schedule_queue
netif_set_real_num_rx_queues
netif_set_real_num_tx_queues
netif_set_xps_queue
netif_tx_stop_all_queues
netif_tx_wake_queue
netlink_broadcast
netlink_unicast
net_ratelimit
nla_find
nla_parse
nla_put
nla_validate
node_data
__node_distance
node_states
node_to_cpumask_map
no_llseek
nonseekable_open
noop_llseek
nr_cpu_ids
nr_node_ids
nsecs_to_jiffies
ns_to_timespec
ns_to_timespec64
ns_to_timeval
numa_node
nvme_alloc_request
nvme_cancel_request
nvme_change_ctrl_state
nvme_cleanup_cmd
nvme_complete_async_event
nvme_complete_rq
nvme_disable_ctrl
nvme_enable_ctrl
nvme_fc_register_localport
nvme_fc_register_remoteport
nvme_fc_set_remoteport_devloss
nvme_fc_unregister_localport
nvme_fc_unregister_remoteport
nvme_init_ctrl
nvme_init_identify
nvme_io_timeout
nvme_kill_queues
nvme_remove_namespaces
nvme_reset_ctrl
nvme_reset_ctrl_sync
nvme_set_queue_count
nvme_setup_cmd
nvme_shutdown_ctrl
nvme_start_ctrl
nvme_start_freeze
nvme_start_queues
nvme_stop_ctrl
nvme_stop_queues
nvme_submit_sync_cmd
nvmet_fc_rcv_fcp_abort
nvmet_fc_rcv_fcp_req
nvmet_fc_rcv_ls_req
nvmet_fc_register_targetport
nvmet_fc_unregister_targetport
nvme_unfreeze
nvme_uninit_ctrl
nvme_wait_freeze
nvme_wait_freeze_timeout
nvme_wq
of_led_classdev_register
on_each_cpu
orderly_poweroff
out_of_line_wait_on_bit
out_of_line_wait_on_bit_lock
override_creds
__page_file_index
__page_frag_cache_drain
page_frag_free
__page_mapcount
page_mapped
page_offset_base
page_pool_alloc_pages
page_pool_create
page_pool_destroy
__page_pool_put_page
pagevec_lookup_range
pagevec_lookup_range_tag
__pagevec_release
panic
panic_notifier_list
param_array_ops
param_get_int
param_ops_bool
param_ops_byte
param_ops_charp
param_ops_int
param_ops_long
param_ops_short
param_ops_string
param_ops_uint
param_ops_ullong
param_ops_ulong
param_ops_ushort
param_set_bool
param_set_int
pat_enabled
pci_alloc_irq_vectors_affinity
pci_assign_unassigned_bus_resources
pcibios_resource_to_bus
pci_bus_resource_n
pci_bus_type
pci_cfg_access_lock
pci_cfg_access_unlock
pci_choose_state
pci_cleanup_aer_uncorrect_error_status
pci_clear_master
pci_clear_mwi
pci_d3cold_disable
pci_dev_driver
pci_dev_get
pci_device_is_present
pci_dev_present
pci_dev_put
pci_disable_device
pci_disable_link_state
pci_disable_msi
pci_disable_msix
pci_disable_pcie_error_reporting
pci_disable_rom
pci_disable_sriov
pcie_bandwidth_available
pcie_capability_clear_and_set_word
pcie_capability_read_dword
pcie_capability_read_word
pcie_capability_write_word
pcie_flr
pcie_get_speed_cap
pcie_get_width_cap
pci_enable_atomic_ops_to_root
pci_enable_device
pci_enable_device_mem
pci_enable_msi
pci_enable_msix_range
pci_enable_pcie_error_reporting
pci_enable_rom
pci_enable_sriov
pci_enable_wake
pcie_print_link_status
pcie_relaxed_ordering_enabled
pcie_set_readrq
pci_find_capability
pci_find_ext_capability
pci_free_irq
pci_free_irq_vectors
pci_get_class
pci_get_device
pci_get_domain_bus_and_slot
pci_get_slot
pci_ignore_hotplug
pci_intx
pci_iomap
pci_ioremap_bar
pci_iounmap
pci_irq_get_affinity
pci_irq_vector
pci_map_rom
pcim_enable_device
pcim_iomap_regions
pcim_iomap_table
pci_num_vf
pci_platform_rom
pci_prepare_to_sleep
pci_read_config_byte
pci_read_config_dword
pci_read_config_word
pci_read_vpd
__pci_register_driver
pci_release_regions
pci_release_resource
pci_release_selected_regions
pci_request_irq
pci_request_regions
pci_request_selected_regions
pci_rescan_bus
pci_resize_resource
pci_restore_state
pci_save_state
pci_select_bars
pci_set_master
pci_set_mwi
pci_set_power_state
pci_sriov_configure_simple
pci_sriov_get_totalvfs
pci_sriov_set_totalvfs
pci_stop_and_remove_bus_device
pci_stop_and_remove_bus_device_locked
pci_try_set_mwi
pci_unmap_rom
pci_unregister_driver
pci_vfs_assigned
pci_vpd_find_info_keyword
pci_vpd_find_tag
pci_wait_for_pending_transaction
pci_wake_from_d3
pci_walk_bus
pci_write_config_byte
pci_write_config_dword
pci_write_config_word
pcix_set_mmrbc
PDE_DATA
__per_cpu_offset
perf_tp_event
perf_trace_buf_alloc
perf_trace_run_bpf_submit
pgprot_writecombine
phy_attached_info
phy_connect
phy_disconnect
phy_ethtool_ksettings_get
phy_ethtool_ksettings_set
phy_ethtool_sset
phy_mii_ioctl
phys_base
physical_mask
phy_start
phy_start_aneg
phy_stop
pid_task
pid_vnr
platform_bus_type
pm_genpd_add_device
pm_genpd_init
pm_genpd_remove_device
pm_power_off
pm_runtime_allow
__pm_runtime_disable
pm_runtime_enable
pm_runtime_forbid
__pm_runtime_idle
__pm_runtime_resume
pm_runtime_set_autosuspend_delay
__pm_runtime_set_status
__pm_runtime_suspend
__pm_runtime_use_autosuspend
pm_schedule_suspend
pm_vt_switch_required
pm_vt_switch_unregister
power_supply_is_system_supplied
prandom_bytes
prandom_seed
prandom_u32
__preempt_count
prepare_creds
prepare_to_wait
prepare_to_wait_event
prepare_to_wait_exclusive
print_hex_dump
printk
__printk_ratelimit
print_stack_trace
proc_create_data
proc_dointvec
proc_mkdir
proc_mkdir_mode
proc_remove
proc_symlink
__pskb_copy_fclone
pskb_expand_head
__pskb_pull_tail
___pskb_trim
ptp_clock_event
ptp_clock_index
ptp_clock_register
ptp_clock_unregister
ptp_find_pin
__put_cred
put_device
__put_devmap_managed_page
put_disk
__put_net
__put_page
put_pid
__put_task_struct
put_unused_fd
__put_user_1
__put_user_2
__put_user_4
__put_user_8
pv_cpu_ops
pv_irq_ops
pv_lock_ops
pv_mmu_ops
qed_get_eth_ops
qed_put_eth_ops
queue_delayed_work_on
queued_read_lock_slowpath
queued_write_lock_slowpath
queue_work_on
radix_tree_delete
radix_tree_gang_lookup
__radix_tree_insert
radix_tree_iter_delete
radix_tree_lookup
radix_tree_lookup_slot
radix_tree_next_chunk
__radix_tree_next_slot
radix_tree_preload
radix_tree_tagged
raid_class_attach
raid_class_release
___ratelimit
raw_notifier_call_chain
raw_notifier_chain_register
raw_notifier_chain_unregister
_raw_read_lock
_raw_read_lock_bh
_raw_read_lock_irq
_raw_read_lock_irqsave
_raw_read_unlock_bh
_raw_read_unlock_irqrestore
_raw_spin_lock
_raw_spin_lock_bh
_raw_spin_lock_irq
_raw_spin_lock_irqsave
_raw_spin_trylock
_raw_spin_unlock_bh
_raw_spin_unlock_irqrestore
_raw_write_lock
_raw_write_lock_bh
_raw_write_lock_irq
_raw_write_lock_irqsave
_raw_write_unlock_bh
_raw_write_unlock_irqrestore
rb_erase
__rb_erase_color
rb_first
rb_first_postorder
__rb_insert_augmented
rb_insert_color
rb_next
rb_next_postorder
rb_replace_node
rbt_ib_umem_for_each_in_range
rbt_ib_umem_lookup
rcu_barrier
rdma_addr_cancel
rdma_addr_size
rdma_create_ah
rdma_create_user_ah
rdma_destroy_ah
rdma_destroy_ah_attr
rdma_find_gid
rdma_find_gid_by_port
rdma_get_gid_attr
rdma_is_zero_gid
rdma_move_ah_attr
rdma_nl_multicast
rdma_nl_register
rdma_nl_unicast
rdma_nl_unicast_wait
rdma_nl_unregister
rdma_node_get_transport
rdma_port_get_link_layer
rdma_put_gid_attr
rdma_query_ah
rdma_query_gid
rdma_resolve_ip
rdma_restrack_del
rdma_roce_rescan_device
rdma_set_cq_moderation
rdma_translate_ip
read_cache_pages
recalc_sigpending
refcount_dec_and_mutex_lock
refcount_dec_and_test_checked
refcount_inc_checked
refcount_inc_not_zero_checked
register_acpi_notifier
register_blkdev
__register_chrdev
register_chrdev_region
register_fib_notifier
register_inet6addr_notifier
register_inetaddr_notifier
register_netdev
register_netdevice_notifier
register_netevent_notifier
register_net_sysctl
__register_nmi_handler
register_pernet_subsys
register_reboot_notifier
release_firmware
release_pages
__release_region
release_sock
remap_pfn_range
remove_conflicting_framebuffers
remove_proc_entry
remove_wait_queue
request_firmware
request_firmware_direct
request_firmware_nowait
__request_module
__request_region
request_threaded_irq
reservation_object_add_excl_fence
reservation_object_add_shared_fence
reservation_object_get_fences_rcu
reservation_object_reserve_shared
reservation_object_wait_timeout_rcu
reservation_ww_class
reset_devices
revert_creds
rhashtable_destroy
rhashtable_free_and_destroy
rhashtable_init
rhashtable_insert_slow
rhashtable_walk_enter
rhashtable_walk_exit
rhashtable_walk_next
rhashtable_walk_start_check
rhashtable_walk_stop
rhltable_init
rht_bucket_nested
rht_bucket_nested_insert
ring_buffer_event_data
roce_gid_type_mask_support
round_jiffies
round_jiffies_relative
rps_may_expire_flow
rt6_lookup
rtc_time64_to_tm
rtnl_is_locked
rtnl_lock
rtnl_trylock
rtnl_unlock
sas_attach_transport
sas_disable_tlr
sas_enable_tlr
sas_end_device_alloc
sas_expander_alloc
sas_is_tlr_enabled
sas_phy_add
sas_phy_alloc
sas_phy_free
sas_port_add
sas_port_add_phy
sas_port_alloc_num
sas_port_delete
sas_port_delete_phy
sas_port_free
sas_read_port_mode_page
sas_release_transport
sas_remove_host
sas_rphy_add
save_stack_trace
save_stack_trace_tsk
sbitmap_queue_clear
__sbitmap_queue_get
sched_setscheduler
schedule
schedule_hrtimeout
schedule_hrtimeout_range
schedule_timeout
schedule_timeout_interruptible
schedule_timeout_uninterruptible
scmd_printk
scnprintf
screen_info
scsi_add_device
scsi_add_host_with_dma
scsi_block_requests
scsi_build_sense_buffer
scsi_change_queue_depth
scsi_device_get
scsi_device_lookup
scsi_device_put
scsi_device_set_state
scsi_device_type
scsi_dma_map
scsi_dma_unmap
__scsi_execute
scsi_get_vpd_page
scsi_host_alloc
scsi_host_busy
scsi_host_get
scsi_host_lookup
scsi_host_put
scsi_internal_device_block_nowait
scsi_internal_device_unblock_nowait
scsi_is_fc_rport
scsi_is_host_device
scsi_is_sdev_device
__scsi_iterate_devices
scsilun_to_int
scsi_normalize_sense
scsi_print_command
scsi_register_driver
scsi_remove_device
scsi_remove_host
scsi_remove_target
scsi_sanitize_inquiry_string
scsi_scan_host
scsi_track_queue_full
scsi_unblock_requests
sdev_prefix_printk
secpath_dup
security_d_instantiate
send_sig
seq_lseek
seq_open
seq_printf
seq_putc
seq_puts
seq_read
seq_release
seq_write
set_cpus_allowed_ptr
set_current_groups
set_device_ro
set_disk_ro
set_freezable
set_memory_array_uc
set_memory_array_wb
set_memory_uc
set_memory_wb
set_memory_wc
set_normalized_timespec
set_normalized_timespec64
set_page_dirty
set_page_dirty_lock
set_user_nice
sg_alloc_table_from_pages
sg_copy_from_buffer
sg_copy_to_buffer
sg_free_table
sg_init_table
sg_miter_next
sg_miter_start
sg_miter_stop
sg_next
show_class_attr_string
sigprocmask
si_meminfo
simple_open
simple_read_from_buffer
simple_strtol
simple_strtoul
simple_strtoull
simple_write_to_buffer
single_open
single_release
skb_add_rx_frag
skb_checksum
skb_checksum_help
skb_clone
skb_clone_tx_timestamp
skb_copy
skb_copy_bits
skb_copy_expand
skb_dequeue
__skb_flow_dissect
__skb_get_hash
__skb_gso_segment
skb_gso_validate_mac_len
__skb_pad
skb_pull
skb_push
skb_put
skb_queue_purge
skb_queue_tail
skb_realloc_headroom
skb_store_bits
skb_trim
skb_tstamp_tx
skb_vlan_pop
sme_active
sme_me_mask
smp_call_function_many
smp_call_function_single
snprintf
sn_rtc_cycles_per_second
sock_create_kern
sock_edemux
sock_release
softnet_data
sort
sprintf
__srcu_read_lock
__srcu_read_unlock
sscanf
__stack_chk_fail
starget_for_each_device
strcasecmp
strcat
strchr
strcmp
strcpy
strcspn
strim
strlcat
strlcpy
strlen
strncasecmp
strncat
strncmp
strncpy
strncpy_from_user
strnlen
strnstr
strpbrk
strrchr
strscpy
strsep
strspn
strstr
submit_bio
__sw_hweight32
__sw_hweight64
swiotlb_nr_tbl
switchdev_port_same_parent_id
__symbol_get
__symbol_put
sync_file_create
synchronize_irq
synchronize_net
synchronize_sched
synchronize_srcu
sysfs_add_file_to_group
sysfs_create_bin_file
sysfs_create_file_ns
sysfs_create_group
sysfs_format_mac
sysfs_remove_bin_file
sysfs_remove_file_from_group
sysfs_remove_file_ns
sysfs_remove_group
sysfs_streq
system_state
system_unbound_wq
system_wq
sys_tz
task_active_pid_ns
tasklet_init
tasklet_kill
__tasklet_schedule
__task_pid_nr_ns
tcf_block_cb_register
tcf_block_cb_unregister
tcp_gro_complete
tcp_hashinfo
tc_setup_cb_egdev_register
tc_setup_cb_egdev_unregister
this_cpu_off
time64_to_tm
timecounter_cyc2time
timecounter_init
timecounter_read
to_drm_sched_fence
trace_define_field
trace_event_buffer_commit
trace_event_buffer_lock_reserve
trace_event_buffer_reserve
trace_event_ignore_this_pid
trace_event_raw_init
trace_event_reg
trace_handle_return
__tracepoint_dma_fence_emit
__tracepoint_xdp_exception
trace_print_flags_seq
trace_raw_output_prep
trace_seq_printf
trace_seq_putc
try_module_get
try_wait_for_completion
tsc_khz
ttm_bo_add_to_lru
ttm_bo_clean_mm
ttm_bo_del_sub_from_lru
ttm_bo_device_init
ttm_bo_device_release
ttm_bo_dma_acc_size
ttm_bo_eviction_valuable
ttm_bo_evict_mm
ttm_bo_global_init
ttm_bo_global_release
ttm_bo_init
ttm_bo_init_mm
ttm_bo_init_reserved
ttm_bo_kmap
ttm_bo_kunmap
ttm_bo_lock_delayed_workqueue
ttm_bo_manager_func
ttm_bo_mem_put
ttm_bo_mem_space
ttm_bo_mmap
ttm_bo_move_accel_cleanup
ttm_bo_move_memcpy
ttm_bo_move_to_lru_tail
ttm_bo_move_ttm
ttm_bo_pipeline_move
ttm_bo_put
ttm_bo_unlock_delayed_workqueue
ttm_bo_validate
ttm_bo_wait
ttm_dma_page_alloc_debugfs
ttm_dma_populate
ttm_dma_tt_fini
ttm_dma_tt_init
ttm_dma_unpopulate
ttm_eu_backoff_reservation
ttm_eu_fence_buffer_objects
ttm_eu_reserve_buffers
ttm_fbdev_mmap
ttm_mem_global_init
ttm_mem_global_release
ttm_page_alloc_debugfs
ttm_pool_populate
ttm_pool_unpopulate
ttm_populate_and_map_pages
ttm_sg_tt_init
ttm_tt_bind
ttm_tt_set_placement_caching
ttm_unmap_and_unpopulate_pages
__udelay
udp4_hwcsum
uio_event_notify
__uio_register_device
uio_unregister_device
unlock_page
unlock_page_memcg
unmap_mapping_range
unregister_acpi_notifier
unregister_blkdev
__unregister_chrdev
unregister_chrdev_region
unregister_fib_notifier
unregister_inet6addr_notifier
unregister_inetaddr_notifier
unregister_netdev
unregister_netdevice_notifier
unregister_netevent_notifier
unregister_net_sysctl_table
unregister_nmi_handler
unregister_pernet_subsys
unregister_reboot_notifier
unuse_mm
up
up_read
up_write
__usecs_to_jiffies
use_mm
usleep_range
__uv_cpu_info
_uverbs_alloc
uverbs_copy_to
uverbs_destroy_def_handler
uverbs_get_flags32
uverbs_get_flags64
uverbs_idr_class
__uv_hub_info_list
uv_possible_blades
uv_setup_irq
uv_teardown_irq
vfree
vga_client_register
vgacon_text_force
vga_set_legacy_decoding
vga_switcheroo_client_fb_set
vga_switcheroo_client_probe_defer
vga_switcheroo_fini_domain_pm_ops
vga_switcheroo_handler_flags
vga_switcheroo_init_domain_pm_ops
vga_switcheroo_lock_ddc
vga_switcheroo_process_delayed_switch
vga_switcheroo_register_client
vga_switcheroo_register_handler
vga_switcheroo_unlock_ddc
vga_switcheroo_unregister_client
vga_switcheroo_unregister_handler
vga_tryget
__virt_addr_valid
vlan_dev_real_dev
vlan_dev_vlan_id
vlan_dev_vlan_proto
vmalloc
__vmalloc
vmalloc_base
vmalloc_node
vmalloc_to_page
vmap
vmemmap_base
vm_get_page_prot
vm_insert_page
vm_mmap
vm_munmap
vprintk
vscnprintf
vsnprintf
vsprintf
vunmap
vzalloc
vzalloc_node
wait_for_completion
wait_for_completion_interruptible
wait_for_completion_interruptible_timeout
wait_for_completion_io_timeout
wait_for_completion_killable
wait_for_completion_timeout
wait_on_page_bit
__wake_up
wake_up_bit
__wake_up_locked
wake_up_process
__warn_printk
wmi_evaluate_method
wmi_has_guid
work_busy
write_cache_pages
ww_mutex_lock
ww_mutex_lock_interruptible
ww_mutex_unlock
x86_cpu_to_apicid
x86_dma_fallback_dev
__x86_indirect_thunk_r10
__x86_indirect_thunk_r11
__x86_indirect_thunk_r12
__x86_indirect_thunk_r13
__x86_indirect_thunk_r14
__x86_indirect_thunk_r15
__x86_indirect_thunk_r8
__x86_indirect_thunk_r9
__x86_indirect_thunk_rax
__x86_indirect_thunk_rbp
__x86_indirect_thunk_rbx
__x86_indirect_thunk_rcx
__x86_indirect_thunk_rdi
__x86_indirect_thunk_rdx
__x86_indirect_thunk_rsi
xdp_do_flush_map
xdp_do_redirect
xdp_return_frame
xdp_return_frame_rx_napi
xdp_rxq_info_is_reg
xdp_rxq_info_reg
xdp_rxq_info_reg_mem_model
xdp_rxq_info_unreg
xdp_rxq_info_unused
xfrm_replay_seqhi
xz_dec_end
xz_dec_init
xz_dec_run
yield
zalloc_cpumask_var
zap_vma_ptes
zlib_inflate
zlib_inflateEnd
zlib_inflateInit2
zlib_inflate_workspacesize
2
2
yanl1229(a)163.com
1
0
[PATCH openEuler-21.03 1/2] mm: add pin memory method for checkpoint add restore
by hejingxian 02 Mar '21
by hejingxian 02 Mar '21
02 Mar '21
From: Jingxian He <hejingxian(a)huawei.com>
Date: Mon, 1 Mar 2021 17:35:32 +0800
Subject: [PATCH openEuler-21.03 1/2] mm: add pin memory method for checkpoint add restore
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
We can use the checkpoint and restore in userspace(criu) method to
dump and restore tasks when updating the kernel.
Currently, criu needs dump all memory data of tasks to files.
When the memory size is very large(larger than 1G),
the cost time of the dumping data will be very long(more than 1 min).
By pin the memory data of tasks and collect the corresponding
physical pages mapping info in checkpoint process,
we can remap the physical pages to restore tasks after
upgrading the kernel. This pin memory method can
restore the task data within one second.
The pin memory area info is saved in the reserved memblock,
which can keep usable in the kernel update process.
The pin memory driver provides the following ioctl command for criu:
1) SET_PIN_MEM_AREA:
Set pin memory area, which can be remap to the restore task.
2) CLEAR_PIN_MEM_AREA:
Clear the pin memory area info,
which enable user reset the pin data.
3) REMAP_PIN_MEM_AREA:
Remap the pages of the pin memory to the restore task.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
Reviewed-by: Wenliang He <hewenliang4(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/configs/openeuler_defconfig | 2 +
arch/arm64/kernel/setup.c | 9 +
arch/arm64/mm/init.c | 60 +++
drivers/char/Kconfig | 6 +
drivers/char/Makefile | 1 +
drivers/char/pin_memory.c | 208 ++++++++
include/linux/crash_core.h | 5 +
include/linux/pin_mem.h | 78 +++
kernel/crash_core.c | 11 +
mm/Kconfig | 8 +
mm/Makefile | 1 +
mm/huge_memory.c | 61 +++
mm/memory.c | 59 ++
mm/pin_mem.c | 950 +++++++++++++++++++++++++++++++++
14 files changed, 1459 insertions(+)
create mode 100644 drivers/char/pin_memory.c
create mode 100644 include/linux/pin_mem.h
create mode 100644 mm/pin_mem.c
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index c5271e7..76fda68 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -1036,6 +1036,7 @@ CONFIG_FRAME_VECTOR=y
# CONFIG_GUP_BENCHMARK is not set
# CONFIG_READ_ONLY_THP_FOR_FS is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_PIN_MEMORY=y
# end of Memory Management options
CONFIG_NET=y
@@ -3282,6 +3283,7 @@ CONFIG_TCG_TIS_ST33ZP24_SPI=y
# CONFIG_RANDOM_TRUST_CPU is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+CONFIG_PIN_MEMORY_DEV=m
#
# I2C support
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c1f1fb9..5e282d3 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -50,6 +50,9 @@
#include <asm/efi.h>
#include <asm/xen/hypervisor.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
static int num_standard_resources;
static struct resource *standard_resources;
@@ -260,6 +263,12 @@ static void __init request_standard_resources(void)
quick_kexec_res.end <= res->end)
request_resource(res, &quick_kexec_res);
#endif
+#ifdef CONFIG_PIN_MEMORY
+ if (pin_memory_resource.end &&
+ pin_memory_resource.start >= res->start &&
+ pin_memory_resource.end <= res->end)
+ request_resource(res, &pin_memory_resource);
+#endif
}
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3e5a66..8ab5aac 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -42,6 +42,9 @@
#include <linux/sizes.h>
#include <asm/tlb.h>
#include <asm/alternative.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
#define ARM64_ZONE_DMA_BITS 30
@@ -78,6 +81,55 @@ static void __init reserve_crashkernel(void)
*/
#define MAX_USABLE_RANGES 2
+#ifdef CONFIG_PIN_MEMORY
+struct resource pin_memory_resource = {
+ .name = "Pin memory",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_RESERVED
+};
+
+static void __init reserve_pin_memory_res(void)
+{
+ unsigned long long mem_start, mem_len;
+ int ret;
+
+ ret = parse_pin_memory(boot_command_line, memblock_phys_mem_size(),
+ &mem_len, &mem_start);
+ if (ret || !mem_len)
+ return;
+
+ mem_len = PAGE_ALIGN(mem_len);
+
+ if (!memblock_is_region_memory(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region is not memory!\n");
+ return;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n");
+ return;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve for pin memory: base address is not 2MB aligned\n");
+ return;
+ }
+
+ memblock_reserve(mem_start, mem_len);
+ pr_debug("pin memory resource reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ mem_start, mem_start + mem_len, mem_len >> 20);
+
+ pin_memory_resource.start = mem_start;
+ pin_memory_resource.end = mem_start + mem_len - 1;
+}
+#else
+static void __init reserve_pin_memory_res(void)
+{
+}
+#endif /* CONFIG_PIN_MEMORY */
+
#ifdef CONFIG_CRASH_DUMP
static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
const char *uname, int depth, void *data)
@@ -455,6 +507,8 @@ void __init arm64_memblock_init(void)
reserve_park_mem();
#endif
+ reserve_pin_memory_res();
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
@@ -583,6 +637,12 @@ void __init mem_init(void)
/* this will put all unused low memory onto the freelists */
memblock_free_all();
+#ifdef CONFIG_PIN_MEMORY
+ /* pre alloc the pages for pin memory */
+ init_reserve_page_map((unsigned long)pin_memory_resource.start,
+ (unsigned long)(pin_memory_resource.end - pin_memory_resource.start + 1));
+#endif
+
mem_init_print_info(NULL);
/*
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index d229a2d..fbb94b8 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -496,3 +496,9 @@ config RANDOM_TRUST_BOOTLOADER
booloader is trustworthy so it will be added to the kernel's entropy
pool. Otherwise, say N here so it will be regarded as device input that
only mixes the entropy pool.
+
+config PIN_MEMORY_DEV
+ bool "/dev/pinmem character device"
+ default m
+ help
+ pin memory driver
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index ffce287..71d76fd 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
obj-$(CONFIG_ADI) += adi.o
+obj-$(CONFIG_PIN_MEMORY_DEV) += pin_memory.o
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
new file mode 100644
index 0000000..f46e056
--- /dev/null
+++ b/drivers/char/pin_memory.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
+ * Pin memory driver for checkpoint and restore.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/mm_types.h>
+#include <linux/processor.h>
+#include <uapi/asm-generic/ioctl.h>
+#include <uapi/asm-generic/mman-common.h>
+#include <uapi/asm/setup.h>
+#include <linux/pin_mem.h>
+#include <linux/sched/mm.h>
+
+#define MAX_PIN_MEM_AREA_NUM 16
+struct _pin_mem_area {
+ unsigned long virt_start;
+ unsigned long virt_end;
+};
+
+struct pin_mem_area_set {
+ unsigned int pid;
+ unsigned int area_num;
+ struct _pin_mem_area mem_area[MAX_PIN_MEM_AREA_NUM];
+};
+
+#define PIN_MEM_MAGIC 0x59
+#define _SET_PIN_MEM_AREA 1
+#define _CLEAR_PIN_MEM_AREA 2
+#define _REMAP_PIN_MEM_AREA 3
+#define _FINISH_PIN_MEM_DUMP 4
+#define _PIN_MEM_IOC_MAX_NR 4
+#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
+#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
+#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+#define FINISH_PIN_MEM_DUMP _IOW(PIN_MEM_MAGIC, _FINISH_PIN_MEM_DUMP, int)
+static int set_pin_mem(struct pin_mem_area_set *pmas)
+{
+ int i;
+ int ret = 0;
+ struct _pin_mem_area *pma;
+ struct mm_struct *mm;
+ struct task_struct *task;
+ struct pid *pid_s;
+
+ pid_s = find_get_pid(pmas->pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pmas->pid);
+ return -EFAULT;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pmas->pid);
+ goto fail;
+ }
+ mm = get_task_mm(task);
+ for (i = 0; i < pmas->area_num; i++) {
+ pma = &(pmas->mem_area[i]);
+ ret = pin_mem_area(task, mm, pma->virt_start, pma->virt_end);
+ if (ret) {
+ mmput(mm);
+ goto fail;
+ }
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return ret;
+
+fail:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static int set_pin_mem_area(unsigned long arg)
+{
+ struct pin_mem_area_set pmas;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(pmas)))
+ return -EFAULT;
+ if (copy_from_user(&pmas, buf, sizeof(pmas)))
+ return -EINVAL;
+ if (pmas.area_num > MAX_PIN_MEM_AREA_NUM) {
+ pr_warn("Input area_num is too large.\n");
+ return -EINVAL;
+ }
+
+ return set_pin_mem(&pmas);
+}
+
+static int pin_mem_remap(unsigned long arg)
+{
+ int pid;
+ struct task_struct *task;
+ struct mm_struct *mm;
+ vm_fault_t ret;
+ void __user *buf = (void __user *)arg;
+ struct pid *pid_s;
+
+ if (!access_ok(buf, sizeof(int)))
+ return -EINVAL;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ return -EINVAL;
+
+ pid_s = find_get_pid(pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pid);
+ return -EINVAL;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pid);
+ goto fault;
+ }
+ mm = get_task_mm(task);
+ ret = do_mem_remap(pid, mm);
+ if (ret) {
+ pr_warn("Handle pin memory remap fail.\n");
+ mmput(mm);
+ goto fault;
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return 0;
+
+fault:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static long pin_memory_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret = 0;
+
+ if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
+ return -EINVAL;
+ if (_IOC_NR(cmd) > _PIN_MEM_IOC_MAX_NR)
+ return -EINVAL;
+
+ switch (cmd) {
+ case SET_PIN_MEM_AREA:
+ ret = set_pin_mem_area(arg);
+ break;
+ case CLEAR_PIN_MEM_AREA:
+ clear_pin_memory_record();
+ break;
+ case REMAP_PIN_MEM_AREA:
+ ret = pin_mem_remap(arg);
+ break;
+ case FINISH_PIN_MEM_DUMP:
+ ret = finish_pin_mem_dump();
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static const struct file_operations pin_memory_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pin_memory_ioctl,
+ .compat_ioctl = pin_memory_ioctl,
+};
+
+static struct miscdevice pin_memory_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pinmem",
+ .fops = &pin_memory_fops,
+};
+
+static int pin_memory_init(void)
+{
+ int err = misc_register(&pin_memory_miscdev);
+
+ if (!err)
+ pr_info("pin_memory init\n");
+ else
+ pr_warn("pin_memory init failed!\n");
+ return err;
+}
+
+static void pin_memory_exit(void)
+{
+ misc_deregister(&pin_memory_miscdev);
+ pr_info("pin_memory ko exists!\n");
+}
+
+module_init(pin_memory_init);
+module_exit(pin_memory_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Euler");
+MODULE_DESCRIPTION("pin memory");
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index fc0ef33..30f0df3 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -87,4 +87,9 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline, unsigned long long system_ram,
+ unsigned long long *pin_size, unsigned long long *pin_base);
+#endif
+
#endif /* LINUX_CRASH_CORE_H */
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
new file mode 100644
index 0000000..bc8b03e
--- /dev/null
+++ b/include/linux/pin_mem.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for checkpoint and restore task.
+ */
+#ifndef _LINUX_PIN_MEMORY_H
+#define _LINUX_PIN_MEMORY_H
+
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/errno.h>
+#include <linux/mm_types.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARM64
+#include <linux/ioport.h>
+#endif
+
+#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)
+
+#define COLLECT_PAGES_FINISH 0
+#define COLLECT_PAGES_NEED_CONTINUE 1
+#define COLLECT_PAGES_FAIL -1
+
+#define COMPOUND_PAD_MASK 0xffffffff
+#define COMPOUND_PAD_START 0x88
+#define COMPOUND_PAD_DELTA 0x40
+#define LIST_POISON4 0xdead000000000400
+#define PAGE_FLAGS_CHECK_RESERVED (1UL << PG_reserved)
+#define SHA256_DIGEST_SIZE 32
+#define next_pme(pme) ((unsigned long *)(pme + 1) + pme->nr_pages)
+#define PIN_MEM_DUMP_MAGIC 0xfeab000000001acd
+struct page_map_entry {
+ unsigned long virt_addr;
+ unsigned int nr_pages;
+ unsigned int is_huge_page;
+ unsigned long redirect_start;
+ unsigned long phy_addr_array[0];
+};
+
+struct page_map_info {
+ int pid;
+ int pid_reserved;
+ unsigned int entry_num;
+ int disable_free_page;
+ struct page_map_entry *pme;
+};
+
+struct pin_mem_dump_info {
+ char sha_digest[SHA256_DIGEST_SIZE];
+ unsigned long magic;
+ unsigned int pin_pid_num;
+ struct page_map_info pmi_array[0];
+};
+
+struct redirect_info {
+ unsigned int redirect_pages;
+ unsigned int redirect_index[0];
+};
+
+extern struct page_map_info *get_page_map_info(int pid);
+extern struct page_map_info *create_page_map_info(int pid);
+extern vm_fault_t do_mem_remap(int pid, struct mm_struct *mm);
+extern vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern void clear_pin_memory_record(void);
+extern int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr);
+extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern int finish_pin_mem_dump(void);
+
+/* reserve space for pin memory*/
+#ifdef CONFIG_ARM64
+extern struct resource pin_memory_resource;
+#endif
+extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+
+#endif /* CONFIG_PIN_MEMORY */
+#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index bfed474..2407de3 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -450,6 +450,17 @@ void __init reserve_crashkernel(void)
}
#endif /* CONFIG_ARCH_WANT_RESERVE_CRASH_KERNEL */
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *pin_size,
+ unsigned long long *pin_base)
+{
+ return __parse_crashkernel(cmdline, system_ram, pin_size, pin_base,
+ "pinmemory=", NULL);
+}
+#endif
+
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
void *data, size_t data_len)
{
diff --git a/mm/Kconfig b/mm/Kconfig
index 390165f..930dc13 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -859,4 +859,12 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config PIN_MEMORY
+ bool "Support for pin memory"
+ depends on CHECKPOINT_RESTORE
+ help
+ Say y here to enable the pin memory feature for checkpoint
+ and restore. We can pin the memory data of tasks and collect
+ the corresponding physical pages mapping info in checkpoint,
+ and remap the physical pages to restore tasks in restore.
endmenu
diff --git a/mm/Makefile b/mm/Makefile
index d73aed0..4963827 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -120,3 +120,4 @@ obj-$(CONFIG_MEMFD_CREATE) += memfd.o
obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o
+obj-$(CONFIG_PIN_MEMORY) += pin_mem.o
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 0bc4a2c..8a11d30 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2996,3 +2996,64 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
update_mmu_cache_pmd(vma, address, pvmw->pmd);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ gfp_t gfp;
+ pgtable_t pgtable;
+ spinlock_t *ptl;
+ pmd_t entry;
+ vm_fault_t ret = 0;
+
+ if (unlikely(anon_vma_prepare(vma)))
+ return VM_FAULT_OOM;
+ if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
+ return VM_FAULT_OOM;
+ gfp = alloc_hugepage_direct_gfpmask(vma);
+ prep_transhuge_page(page);
+ if (mem_cgroup_charge(page, vma->vm_mm, gfp)) {
+ put_page(page);
+ count_vm_event(THP_FAULT_FALLBACK);
+ count_vm_event(THP_FAULT_FALLBACK_CHARGE);
+ return VM_FAULT_FALLBACK;
+ }
+ cgroup_throttle_swaprate(page, gfp);
+
+ pgtable = pte_alloc_one(vma->vm_mm);
+ if (unlikely(!pgtable)) {
+ ret = VM_FAULT_OOM;
+ goto release;
+ }
+ __SetPageUptodate(page);
+ ptl = pmd_lock(vma->vm_mm, pmd);
+ if (unlikely(!pmd_none(*pmd))) {
+ goto unlock_release;
+ } else {
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto unlock_release;
+ entry = mk_huge_pmd(page, vma->vm_page_prot);
+ entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+ page_add_new_anon_rmap(page, vma, address, true);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+ pgtable_trans_huge_deposit(vma->vm_mm, pmd, pgtable);
+ set_pmd_at(vma->vm_mm, address, pmd, entry);
+ add_mm_counter(vma->vm_mm, MM_ANONPAGES, HPAGE_PMD_NR);
+ mm_inc_nr_ptes(vma->vm_mm);
+ spin_unlock(ptl);
+ count_vm_event(THP_FAULT_ALLOC);
+ count_memcg_event_mm(vma->vm_mm, THP_FAULT_ALLOC);
+ }
+
+ return 0;
+unlock_release:
+ spin_unlock(ptl);
+release:
+ if (pgtable)
+ pte_free(vma->vm_mm, pgtable);
+ put_page(page);
+ return ret;
+}
+#endif
diff --git a/mm/memory.c b/mm/memory.c
index 50632c4..7b7f1a7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5248,3 +5248,62 @@ void ptlock_free(struct page *page)
kmem_cache_free(page_ptl_cachep, page->ptl);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ pte_t entry;
+ spinlock_t *ptl;
+ pte_t *pte;
+ vm_fault_t ret = 0;
+
+ if (pte_alloc(vma->vm_mm, pmd))
+ return VM_FAULT_OOM;
+
+ /* See the comment in pte_alloc_one_map() */
+ if (unlikely(pmd_trans_unstable(pmd)))
+ return 0;
+
+ /* Allocate our own private page. */
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+
+ if (mem_cgroup_charge(page, vma->vm_mm, GFP_KERNEL))
+ goto oom_free_page;
+ cgroup_throttle_swaprate(page, GFP_KERNEL);
+
+ __SetPageUptodate(page);
+
+ entry = mk_pte(page, vma->vm_page_prot);
+ if (vma->vm_flags & VM_WRITE)
+ entry = pte_mkwrite(pte_mkdirty(entry));
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, address,
+ &ptl);
+ if (!pte_none(*pte)) {
+ ret = VM_FAULT_FALLBACK;
+ goto release;
+ }
+
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto release;
+ inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
+ page_add_new_anon_rmap(page, vma, address, false);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+
+ set_pte_at(vma->vm_mm, address, pte, entry);
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, pte);
+unlock:
+ pte_unmap_unlock(pte, ptl);
+ return ret;
+release:
+ put_page(page);
+ goto unlock;
+oom_free_page:
+ put_page(page);
+oom:
+ return VM_FAULT_OOM;
+}
+#endif
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
new file mode 100644
index 0000000..0a143b6
--- /dev/null
+++ b/mm/pin_mem.c
@@ -0,0 +1,950 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for checkpoint and restore task.
+ */
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched/cputime.h>
+#include <linux/tick.h>
+#include <linux/mm.h>
+#include <linux/pin_mem.h>
+#include <linux/idr.h>
+#include <linux/page-isolation.h>
+#include <linux/sched/mm.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <crypto/sha.h>
+
+#define MAX_PIN_PID_NUM 128
+static DEFINE_SPINLOCK(page_map_entry_lock);
+
+struct pin_mem_dump_info *pin_mem_dump_start;
+unsigned int pin_pid_num;
+static unsigned int *pin_pid_num_addr;
+static unsigned long __page_map_entry_start;
+static unsigned long page_map_entry_end;
+static struct page_map_info *user_space_reserve_start;
+static struct page_map_entry *page_map_entry_start;
+unsigned int max_pin_pid_num __read_mostly;
+unsigned long redirect_space_size;
+unsigned long redirect_space_start;
+#define DEFAULT_REDIRECT_SPACE_SIZE 0x100000
+
+static int __init setup_max_pin_pid_num(char *str)
+{
+ int ret = 0;
+
+ if (!str)
+ goto out;
+
+ ret = kstrtouint(str, 10, &max_pin_pid_num);
+out:
+ if (ret) {
+ pr_warn("Unable to parse max pin pid num.\n");
+ } else {
+ if (max_pin_pid_num > MAX_PIN_PID_NUM) {
+ max_pin_pid_num = 0;
+ pr_warn("Input max_pin_pid_num is too large.\n");
+ }
+ }
+ return ret;
+}
+early_param("max_pin_pid_num", setup_max_pin_pid_num);
+
+static int __init setup_redirect_space_size(char *str)
+{
+ if (!str)
+ goto out;
+
+ redirect_space_size = memparse(str, NULL);
+out:
+ if (!redirect_space_size) {
+ pr_warn("Unable to parse redirect space size, use the default value.\n");
+ redirect_space_size = DEFAULT_REDIRECT_SPACE_SIZE;
+ }
+ return 0;
+}
+early_param("redirect_space_size", setup_redirect_space_size);
+
+struct page_map_info *create_page_map_info(int pid)
+{
+ struct page_map_info *new;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ if (pin_pid_num >= max_pin_pid_num) {
+ pr_warn("Pin pid num too large than max_pin_pid_num, fail create: %d!", pid);
+ return NULL;
+ }
+ new = (struct page_map_info *)(user_space_reserve_start + pin_pid_num);
+ new->pid = pid;
+ new->pme = NULL;
+ new->entry_num = 0;
+ new->pid_reserved = false;
+ new->disable_free_page = false;
+ (*pin_pid_num_addr)++;
+ pin_pid_num++;
+ return new;
+}
+EXPORT_SYMBOL_GPL(create_page_map_info);
+
+struct page_map_info *get_page_map_info(int pid)
+{
+ int i;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ for (i = 0; i < pin_pid_num; i++) {
+ if (user_space_reserve_start[i].pid == pid)
+ return &(user_space_reserve_start[i]);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(get_page_map_info);
+
+static struct page *find_head_page(struct page *page)
+{
+ struct page *p = page;
+
+ while (!PageBuddy(p)) {
+ if (PageLRU(p))
+ return NULL;
+ p--;
+ }
+ return p;
+}
+
+static void spilt_page_area_left(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ unsigned long total_size = 0;
+
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ list_add(&page[total_size].lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(page[total_size]._mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(&page[total_size], order);
+ set_pageblock_migratetype(&page[total_size], MIGRATE_MOVABLE);
+ area->nr_free++;
+ total_size += cur_size;
+ size -= cur_size;
+ }
+ }
+}
+
+static void spilt_page_area_right(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ struct page *right_page, *head_page;
+
+ right_page = page + size;
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ head_page = right_page - cur_size;
+ list_add(&head_page->lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(head_page->_mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(head_page, order);
+ set_pageblock_migratetype(head_page, MIGRATE_MOVABLE);
+ area->nr_free++;
+ size -= cur_size;
+ right_page = head_page;
+ }
+ }
+}
+
+void reserve_page_from_buddy(unsigned long nr_pages, struct page *page)
+{
+ unsigned int current_order;
+ struct page *page_end;
+ struct free_area *area;
+ struct zone *zone;
+ struct page *head_page;
+
+ head_page = find_head_page(page);
+ if (!head_page) {
+ pr_warn("Find page head fail.");
+ return;
+ }
+ current_order = head_page->private;
+ page_end = head_page + (1 << current_order);
+ zone = page_zone(head_page);
+ area = &(zone->free_area[current_order]);
+ list_del(&head_page->lru);
+ atomic_set(&head_page->_mapcount, -1);
+ set_page_private(head_page, 0);
+ area->nr_free--;
+ if (head_page != page)
+ spilt_page_area_left(zone, area, head_page,
+ (unsigned long)(page - head_page), current_order);
+ page = page + nr_pages;
+ if (page < page_end) {
+ spilt_page_area_right(zone, area, page,
+ (unsigned long)(page_end - page), current_order);
+ } else if (page > page_end) {
+ pr_warn("Find page end smaller than page.");
+ }
+}
+
+static inline void reserve_user_normal_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy(1, page);
+}
+
+static void init_huge_pmd_pages(struct page *head_page)
+{
+ int i = 0;
+ struct page *page = head_page;
+
+ __set_bit(PG_head, &page->flags);
+ __set_bit(PG_active, &page->flags);
+ atomic_set(&page->_refcount, 1);
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ page->compound_dtor = HUGETLB_PAGE_DTOR + 1;
+ page->compound_order = HPAGE_PMD_ORDER;
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ i++;
+ INIT_LIST_HEAD(&(page->deferred_list));
+ for (; i < HPAGE_PMD_NR; i++) {
+ page = head_page + i;
+ page->compound_head = (unsigned long)head_page + 1;
+ }
+}
+
+static inline void reserve_user_huge_pmd_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy((1 << HPAGE_PMD_ORDER), page);
+ init_huge_pmd_pages(page);
+}
+
+int reserve_user_map_pages_fail;
+
+void free_user_map_pages(unsigned int pid_index, unsigned int entry_index, unsigned int page_index)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ for (index = 0; index < pid_index; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < entry_index; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ for (j = 0; j < page_index; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+}
+
+bool check_redirect_end_valid(struct redirect_info *redirect_start,
+ unsigned long max_redirect_page_num)
+{
+ unsigned long redirect_end;
+
+ redirect_end = ((unsigned long)(redirect_start + 1) +
+ max_redirect_page_num * sizeof(unsigned int));
+ if (redirect_end > redirect_space_start + redirect_space_size)
+ return false;
+ return false;
+}
+
+static void reserve_user_space_map_pages(void)
+{
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned int i, j, index;
+ struct page *page;
+ unsigned long flags;
+ unsigned long phy_addr;
+ unsigned long redirect_pages = 0;
+ struct redirect_info *redirect_start = (struct redirect_info *)redirect_space_start;
+
+ if (!user_space_reserve_start || !redirect_start)
+ return;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ redirect_pages = 0;
+ if (!check_redirect_end_valid(redirect_start, pme->nr_pages))
+ redirect_start = NULL;
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (atomic_read(&page->_refcount)) {
+ if ((page->flags & PAGE_FLAGS_CHECK_RESERVED)
+ && !pme->redirect_start)
+ pme->redirect_start =
+ (unsigned long)redirect_start;
+ if (redirect_start &&
+ (page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ redirect_start->redirect_index[redirect_pages] = j;
+ redirect_pages++;
+ continue;
+ } else {
+ reserve_user_map_pages_fail = 1;
+ pr_warn("Page %pK refcount %d large than zero, no need reserve.\n",
+ page, atomic_read(&page->_refcount));
+ goto free_pages;
+ }
+ }
+ if (!pme->is_huge_page)
+ reserve_user_normal_pages(page);
+ else
+ reserve_user_huge_pmd_pages(page);
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ if (redirect_pages && redirect_start) {
+ redirect_start->redirect_pages = redirect_pages;
+ redirect_start = (struct redirect_info *)(
+ (unsigned long)(redirect_start + 1) +
+ redirect_start->redirect_pages * sizeof(unsigned int));
+ }
+ }
+ }
+ spin_unlock(&page_map_entry_lock);
+ return;
+free_pages:
+ free_user_map_pages(index, i, j);
+ spin_unlock(&page_map_entry_lock);
+}
+
+
+int calculate_pin_mem_digest(struct pin_mem_dump_info *pmdi, char *digest)
+{
+ int i;
+ struct sha256_state sctx;
+
+ if (!digest)
+ digest = pmdi->sha_digest;
+ sha256_init(&sctx);
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->magic)),
+ sizeof(struct pin_mem_dump_info) - SHA256_DIGEST_SIZE);
+ for (i = 0; i < pmdi->pin_pid_num; i++) {
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->pmi_array[i])),
+ sizeof(struct page_map_info));
+ }
+ sha256_final(&sctx, digest);
+ return 0;
+}
+
+static int check_sha_digest(struct pin_mem_dump_info *pmdi)
+{
+ int ret = 0;
+ char digest[SHA256_DIGEST_SIZE] = {0};
+
+ ret = calculate_pin_mem_digest(pmdi, digest);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ if (memcmp(pmdi->sha_digest, digest, SHA256_DIGEST_SIZE)) {
+ pr_warn("pin mem dump info sha256 digest match error!\n");
+ return -EFAULT;
+ }
+ return ret;
+}
+
+/*
+ * The whole page map entry collect process must be Sequentially.
+ * The user_space_reserve_start points to the first page map info for
+ * the first dump task. And the page_map_entry_start points to
+ * the first page map entry of the first dump vma.
+ */
+static void init_page_map_info(struct pin_mem_dump_info *pmdi, unsigned long map_len)
+{
+ if (pin_mem_dump_start || !max_pin_pid_num) {
+ pr_warn("pin page map already init or max_pin_pid_num not set.\n");
+ return;
+ }
+ if (map_len < sizeof(struct pin_mem_dump_info) +
+ max_pin_pid_num * sizeof(struct page_map_info) + redirect_space_size) {
+ pr_warn("pin memory reserved memblock too small.\n");
+ return;
+ }
+ if ((pmdi->magic != PIN_MEM_DUMP_MAGIC) || (pmdi->pin_pid_num > max_pin_pid_num) ||
+ check_sha_digest(pmdi))
+ memset(pmdi, 0, sizeof(struct pin_mem_dump_info));
+ pin_mem_dump_start = pmdi;
+ pin_pid_num = pmdi->pin_pid_num;
+ pr_info("pin_pid_num: %d\n", pin_pid_num);
+ pin_pid_num_addr = &(pmdi->pin_pid_num);
+ user_space_reserve_start =
+ (struct page_map_info *)pmdi->pmi_array;
+ page_map_entry_start =
+ (struct page_map_entry *)(user_space_reserve_start + max_pin_pid_num);
+ page_map_entry_end = (unsigned long)pmdi + map_len - redirect_space_size;
+ redirect_space_start = page_map_entry_end;
+ if (pin_pid_num > 0)
+ reserve_user_space_map_pages();
+}
+
+int finish_pin_mem_dump(void)
+{
+ int ret;
+
+ pin_mem_dump_start->magic = PIN_MEM_DUMP_MAGIC;
+ memset(pin_mem_dump_start->sha_digest, 0, SHA256_DIGEST_SIZE);
+ ret = calculate_pin_mem_digest(pin_mem_dump_start, NULL);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ return ret;
+}
+
+int collect_pmd_huge_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ long res;
+ int index = 0;
+ unsigned long start = start_addr;
+ struct page *temp_page;
+
+ while (start < end_addr) {
+ temp_page = NULL;
+ res = get_user_pages_remote(task->mm, start, 1,
+ FOLL_TOUCH | FOLL_GET, &temp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get huge page for addr(%lx) fail.", start);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(temp_page)) {
+ start += HPAGE_PMD_SIZE;
+ pme->phy_addr_array[index] = page_to_phys(temp_page);
+ index++;
+ } else {
+ pme->nr_pages = index;
+ atomic_dec(&((temp_page)->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ }
+ pme->nr_pages = index;
+ return COLLECT_PAGES_FINISH;
+}
+
+int collect_normal_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ int res;
+ unsigned long next;
+ unsigned long i, nr_pages;
+ struct page *tmp_page;
+ unsigned long *phy_addr_array = pme->phy_addr_array;
+ struct page **page_array = (struct page **)pme->phy_addr_array;
+
+ next = (start_addr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
+ next = (next > end_addr) ? end_addr : next;
+ pme->nr_pages = 0;
+ while (start_addr < next) {
+ nr_pages = (PAGE_ALIGN(next) - start_addr) / PAGE_SIZE;
+ res = get_user_pages_remote(task->mm, start_addr, 1,
+ FOLL_TOUCH | FOLL_GET, &tmp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user page of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(tmp_page)) {
+ atomic_dec(&(tmp_page->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ atomic_dec(&(tmp_page->_refcount));
+ if (PageTail(tmp_page)) {
+ start_addr = next;
+ pme->virt_addr = start_addr;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ?
+ end_addr : (next + HPAGE_PMD_SIZE);
+ continue;
+ }
+ res = get_user_pages_remote(task->mm, start_addr, nr_pages,
+ FOLL_TOUCH | FOLL_GET, page_array, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user pages of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ for (i = 0; i < nr_pages; i++)
+ phy_addr_array[i] = page_to_phys(page_array[i]);
+ pme->nr_pages += nr_pages;
+ page_array += nr_pages;
+ phy_addr_array += nr_pages;
+ start_addr = next;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ? end_addr : (next + HPAGE_PMD_SIZE);
+ }
+ return COLLECT_PAGES_FINISH;
+}
+
+/* Users make sure that the pin memory belongs to anonymous vma. */
+int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr)
+{
+ int pid, ret;
+ int is_huge_page = false;
+ unsigned int page_size;
+ unsigned long nr_pages, flags;
+ struct page_map_entry *pme;
+ struct page_map_info *pmi;
+ struct vm_area_struct *vma;
+ unsigned long i;
+ struct page *tmp_page;
+
+ if (!page_map_entry_start
+ || !task || !mm
+ || start_addr >= end_addr)
+ return -EFAULT;
+
+ pid = task->pid;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ nr_pages = ((end_addr - start_addr) / PAGE_SIZE);
+ if ((unsigned long)page_map_entry_start + nr_pages * sizeof(struct page *) >=
+ page_map_entry_end) {
+ pr_warn("Page map entry use up!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ vma = find_extend_vma(mm, start_addr);
+ if (!vma) {
+ pr_warn("Find no match vma!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (start_addr == (start_addr & HPAGE_PMD_MASK) &&
+ transparent_hugepage_enabled(vma)) {
+ page_size = HPAGE_PMD_SIZE;
+ is_huge_page = true;
+ } else {
+ page_size = PAGE_SIZE;
+ }
+ pme = page_map_entry_start;
+ pme->virt_addr = start_addr;
+ pme->redirect_start = 0;
+ pme->is_huge_page = is_huge_page;
+ memset(pme->phy_addr_array, 0, nr_pages * sizeof(unsigned long));
+ down_write(&mm->mmap_lock);
+ if (!is_huge_page) {
+ ret = collect_normal_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = true;
+ page_size = HPAGE_PMD_SIZE;
+ ret = collect_pmd_huge_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ } else {
+ ret = collect_pmd_huge_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = false;
+ page_size = PAGE_SIZE;
+ ret = collect_normal_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ }
+ up_write(&mm->mmap_lock);
+ if (ret == COLLECT_PAGES_FAIL) {
+ ret = -EFAULT;
+ goto finish;
+ }
+
+ /* check for zero pages */
+ for (i = 0; i < pme->nr_pages; i++) {
+ tmp_page = phys_to_page(pme->phy_addr_array[i]);
+ if (!pme->is_huge_page) {
+ if (page_to_pfn(tmp_page) == my_zero_pfn(pme->virt_addr + i * PAGE_SIZE))
+ pme->phy_addr_array[i] = 0;
+ } else if (is_huge_zero_page(tmp_page))
+ pme->phy_addr_array[i] = 0;
+ }
+
+ page_map_entry_start = (struct page_map_entry *)(next_pme(pme));
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ pmi = create_page_map_info(pid);
+ if (!pmi) {
+ pr_warn("Create page map info fail for pid: %d!\n", pid);
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (!pmi->pme)
+ pmi->pme = pme;
+ pmi->entry_num++;
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ if (ret == COLLECT_PAGES_NEED_CONTINUE)
+ ret = pin_mem_area(task, mm, pme->virt_addr + pme->nr_pages * page_size, end_addr);
+ return ret;
+finish:
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pin_mem_area);
+
+vm_fault_t remap_normal_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * PAGE_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (page_to_pfn(page) == my_zero_pfn(address)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ new = alloc_zeroed_user_highpage_movable(vma, address);
+ if (!new) {
+ pr_warn("Redirect alloc page fail\n");
+ continue;
+ }
+ copy_page(page_to_virt(new), phys_to_virt(phy_addr));
+ page = new;
+ redirect_pages++;
+ }
+ page->mapping = NULL;
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ __free_page(phys_to_page(phy_addr));
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ return ret;
+}
+
+static inline gfp_t get_hugepage_gfpmask(struct vm_area_struct *vma)
+{
+ const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ __GFP_KSWAPD_RECLAIM);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ 0);
+ return GFP_TRANSHUGE_LIGHT;
+}
+
+vm_fault_t remap_huge_pmd_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ gfp_t gfp;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * HPAGE_PMD_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (is_huge_zero_page(page)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ gfp = get_hugepage_gfpmask(vma);
+ new = alloc_hugepage_vma(gfp, vma, address, HPAGE_PMD_ORDER);
+ if (!new) {
+ pr_warn("Redirect alloc huge page fail\n");
+ continue;
+ }
+ memcpy(page_to_virt(new), phys_to_virt(phy_addr), HPAGE_PMD_SIZE);
+ page = new;
+ redirect_pages++;
+ }
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_huge_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, HPAGE_PMD_ORDER);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ return ret;
+}
+
+static void free_unmap_pages(struct page_map_info *pmi,
+ struct page_map_entry *pme,
+ unsigned int index)
+{
+ unsigned int i, j;
+ unsigned long phy_addr;
+ unsigned int order;
+ struct page *page;
+
+ pme = (struct page_map_entry *)(next_pme(pme));
+ for (i = index; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ }
+}
+
+vm_fault_t do_mem_remap(int pid, struct mm_struct *mm)
+{
+ unsigned int i = 0;
+ vm_fault_t ret = 0;
+ struct vm_area_struct *vma;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned long flags;
+
+ if (reserve_user_map_pages_fail)
+ return -EFAULT;
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ return -EFAULT;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ pmi->disable_free_page = true;
+ spin_unlock(&page_map_entry_lock);
+ down_write(&mm->mmap_lock);
+ pme = pmi->pme;
+ vma = mm->mmap;
+ while ((i < pmi->entry_num) && (vma != NULL)) {
+ if (pme->virt_addr >= vma->vm_start && pme->virt_addr < vma->vm_end) {
+ i++;
+ if (!vma_is_anonymous(vma)) {
+ pme = (struct page_map_entry *)(next_pme(pme));
+ continue;
+ }
+ if (!pme->is_huge_page) {
+ ret = remap_normal_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ } else {
+ ret = remap_huge_pmd_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ } else {
+ vma = vma->vm_next;
+ }
+ }
+ up_write(&mm->mmap_lock);
+ return 0;
+free:
+ free_unmap_pages(pmi, pme, i);
+ up_write(&mm->mmap_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(do_mem_remap);
+
+#if defined(CONFIG_ARM64)
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+ void *addr;
+
+ if (!map_addr || !map_size)
+ return;
+ addr = phys_to_virt(map_addr);
+ init_page_map_info((struct pin_mem_dump_info *)addr, map_size);
+}
+#else
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+}
+#endif
+
+static void free_all_reserved_pages(void)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ if (!user_space_reserve_start || reserve_user_map_pages_fail)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->disable_free_page)
+ continue;
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+}
+
+/* Clear all pin memory record. */
+void clear_pin_memory_record(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ free_all_reserved_pages();
+ if (pin_pid_num_addr) {
+ *pin_pid_num_addr = 0;
+ pin_pid_num = 0;
+ page_map_entry_start = (struct page_map_entry *)__page_map_entry_start;
+ }
+ spin_unlock(&page_map_entry_lock);
+}
+EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+
+#endif /* CONFIG_PIN_MEMORY */
--
2.9.5
2
1
尊敬的linux内核组各位老师同学:
你们好!
我是北京拓林思软件有限公司的员工邓伟进。我对linux内核进程管理,文件系统和
设备驱动有一定理解。熟悉bpf。目前正努力致力于研究学习bpf和linux内核进程管
理,内存管理和文件系统。热爱操作系统和编程。严谨,并喜欢刨根究底的探究问
题。这次在陈琪德老师鼓励下申请加入linux内核组,还望通过!非常感谢,我会
争取能为社区做一些力所能及的工作。
期待您的回复!
邓伟进 2021.3.2
2
1
From: zhuling <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Enabled e820_pmem in arm64:
Use memmap=nn[KMG]!ss[KMG] reserve memory for persistent storage
when the kernel restart or update. the data in PMEM will not be lost
and can be loaded faster.this is a general features.
if you want use this features, you need do as follows:
1.reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.insmod nd_e820.ko: modprobe nd_e820.
3.check pmem device in /dev exp: /dev/pmem0.
Signed-off-by: zhuling <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 24 ++++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 6 +++
arch/arm64/mm/init.c | 98 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Makefile | 1 +
include/linux/mm.h | 4 ++
7 files changed, 169 insertions(+)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b9c56543c..f1e05d9d2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1141,6 +1141,30 @@ config XEN_DOM0
def_bool y
depends on XEN
+config ARM64_PMEM_LEGACY_DEVICE
+ bool
+
+config ARM64_PMEM_RESERVE
+ bool "reserve memory for persistent storage"
+ default y
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve memory for
+ persistent storage
+
+ Say y here to enable this feature
+
+config ARM64_PMEM_LEGACY
+ tristate "create persistent storage"
+ depends on ARM64_PMEM_RESERVE
+ depends on BLK_DEV
+ select ARM64_PMEM_LEGACY_DEVICE
+ select LIBNVDIMM
+ help
+ Use reserved memory for persistent storage when the kernel restart
+ or update. the data in PMEM will not be lost and can be loaded faster.
+
+ Say y if unsure.
+
config XEN
bool "Xen guest support on ARM64"
depends on ARM64 && OF
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2621d5c2b..c363639b8 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o
obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 6aff30de8..7f506036d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -255,6 +255,12 @@ static void __init request_standard_resources(void)
request_resource(res, &crashk_res);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 794f992cb..e4dc19145 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -63,6 +63,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -236,6 +248,88 @@ static void __init fdt_enforce_memory_region(void)
memblock_add(usable_rgns[1].base, usable_rgns[1].size);
}
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+ int ret;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -359,6 +453,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..b97760e9f 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_ARM64_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
diff --git a/include/linux/mm.h b/include/linux/mm.h
index cd5c31372..a5e50495e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -45,6 +45,10 @@ extern int sysctl_page_lock_unfairness;
void init_mm_internals(void);
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
#ifndef CONFIG_NEED_MULTIPLE_NODES /* Don't use mapnrs, do it properly */
extern unsigned long max_mapnr;
--
2.19.1
2
1
[PATCH openEuler-21.03 2/2] pid: add pid reserve method for checkpoint and recover
by hejingxian 02 Mar '21
by hejingxian 02 Mar '21
02 Mar '21
From: Jingxian He <hejingxian(a)huawei.com>
Date: Mon, 1 Mar 2021 17:44:59 +0800
Subject: [PATCH openEuler-21.03 2/2] pid: add pid reserve method for checkpoint and recover
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
We record the pid of dump tasks in the reserved memory,
and reserve the pids before init task start.
In the recover process, free the reserved pids and realloc them for use.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
Reviewed-by: Wenliang He <hewenliang4(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/configs/openeuler_defconfig | 1 +
include/linux/pin_mem.h | 6 ++++
kernel/pid.c | 10 +++++++
mm/Kconfig | 10 +++++++
mm/pin_mem.c | 51 ++++++++++++++++++++++++++++++++++
5 files changed, 78 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index 76fda68..de6db02 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -1037,6 +1037,7 @@ CONFIG_FRAME_VECTOR=y
# CONFIG_READ_ONLY_THP_FOR_FS is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
CONFIG_PIN_MEMORY=y
+CONFIG_PID_RESERVE=y
# end of Memory Management options
CONFIG_NET=y
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
index bc8b03e..a9fe2ef 100644
--- a/include/linux/pin_mem.h
+++ b/include/linux/pin_mem.h
@@ -74,5 +74,11 @@ extern struct resource pin_memory_resource;
#endif
extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+#ifdef CONFIG_PID_RESERVE
+extern bool is_need_reserve_pids(void);
+extern void free_reserved_pid(struct idr *idr, int pid);
+extern void reserve_pids(struct idr *idr, int pid_max);
+#endif
+
#endif /* CONFIG_PIN_MEMORY */
#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/pid.c b/kernel/pid.c
index 4856818..32ab9ef 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -44,6 +44,9 @@
#include <linux/idr.h>
#include <net/sock.h>
#include <uapi/linux/pidfd.h>
+#ifdef CONFIG_PID_RESERVE
+#include <linux/pin_mem.h>
+#endif
struct pid init_struct_pid = {
.count = REFCOUNT_INIT(1),
@@ -209,6 +212,9 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
spin_lock_irq(&pidmap_lock);
if (tid) {
+#ifdef CONFIG_PID_RESERVE
+ free_reserved_pid(&tmp->idr, tid);
+#endif
nr = idr_alloc(&tmp->idr, NULL, tid,
tid + 1, GFP_ATOMIC);
/*
@@ -621,6 +627,10 @@ void __init pid_idr_init(void)
init_pid_ns.pid_cachep = KMEM_CACHE(pid,
SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT);
+#ifdef CONFIG_PID_RESERVE
+ if (is_need_reserve_pids())
+ reserve_pids(&init_pid_ns.idr, pid_max);
+#endif
}
static struct file *__pidfd_fget(struct task_struct *task, int fd)
diff --git a/mm/Kconfig b/mm/Kconfig
index 930dc13..e27d2c6 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -868,3 +868,13 @@ config PIN_MEMORY
the corresponding physical pages mapping info in checkpoint,
and remap the physical pages to restore tasks in restore.
endmenu
+
+config PID_RESERVE
+ bool "Support for reserve pid"
+ depends on PIN_MEMORY
+ help
+ Say y here to enable the pid reserved feature for checkpoint.
+ and restore.
+ We record the pid of dump task in the reserve memory,
+ and reserve the pids before init task start. In restore process,
+ free the reserved pids and realloc them for use.
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
index 0a143b6..a040853 100644
--- a/mm/pin_mem.c
+++ b/mm/pin_mem.c
@@ -947,4 +947,55 @@ void clear_pin_memory_record(void)
}
EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+#ifdef CONFIG_PID_RESERVE
+struct idr *reserve_idr;
+
+/* test if there exist pin memory tasks */
+bool is_need_reserve_pids(void)
+{
+ return (pin_pid_num > 0);
+}
+
+void free_reserved_pid(struct idr *idr, int pid)
+{
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num || idr != reserve_idr)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->pid == pid && pmi->pid_reserved) {
+ idr_remove(idr, pid);
+ return;
+ }
+ }
+}
+
+/* reserve pids for check point tasks which pinned memory */
+void reserve_pids(struct idr *idr, int pid_max)
+{
+ int alloc_pid;
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num)
+ return;
+ reserve_idr = idr;
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pmi->pid_reserved = true;
+ alloc_pid = idr_alloc(idr, NULL, pmi->pid, pid_max, GFP_ATOMIC);
+ if (alloc_pid != pmi->pid) {
+ if (alloc_pid > 0)
+ idr_remove(idr, alloc_pid);
+ pr_warn("Reserve pid (%d) fail, real pid is %d.\n", alloc_pid, pmi->pid);
+ pmi->pid_reserved = false;
+ continue;
+ }
+ }
+}
+#endif /* CONFIG_PID_RESERVE */
+
#endif /* CONFIG_PIN_MEMORY */
--
2.9.5
1
0
[PATCH openEuler-21.03 1/2] mm: add pin memory method for checkpoint add restore
by hejingxian@huawei.com 02 Mar '21
by hejingxian@huawei.com 02 Mar '21
02 Mar '21
From: Jingxian He <hejingxian(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
We can use the checkpoint and restore in userspace(criu) method to
dump and restore tasks when updating the kernel.
Currently, criu needs dump all memory data of tasks to files.
When the memory size is very large(larger than 1G),
the cost time of the dumping data will be very long(more than 1 min).
By pin the memory data of tasks and collect the corresponding
physical pages mapping info in checkpoint process,
we can remap the physical pages to restore tasks after
upgrading the kernel. This pin memory method can
restore the task data within one second.
The pin memory area info is saved in the reserved memblock,
which can keep usable in the kernel update process.
The pin memory driver provides the following ioctl command for criu:
1) SET_PIN_MEM_AREA:
Set pin memory area, which can be remap to the restore task.
2) CLEAR_PIN_MEM_AREA:
Clear the pin memory area info,
which enable user reset the pin data.
3) REMAP_PIN_MEM_AREA:
Remap the pages of the pin memory to the restore task.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
Reviewed-by: Wenliang He <hewenliang4(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/configs/openeuler_defconfig | 2 +
arch/arm64/kernel/setup.c | 9 +
arch/arm64/mm/init.c | 60 +++
drivers/char/Kconfig | 6 +
drivers/char/Makefile | 1 +
drivers/char/pin_memory.c | 208 ++++++++
include/linux/crash_core.h | 5 +
include/linux/pin_mem.h | 78 +++
kernel/crash_core.c | 11 +
mm/Kconfig | 8 +
mm/Makefile | 1 +
mm/huge_memory.c | 61 +++
mm/memory.c | 59 ++
mm/pin_mem.c | 950 +++++++++++++++++++++++++++++++++
14 files changed, 1459 insertions(+)
create mode 100644 drivers/char/pin_memory.c
create mode 100644 include/linux/pin_mem.h
create mode 100644 mm/pin_mem.c
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index c5271e7..76fda68 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -1036,6 +1036,7 @@ CONFIG_FRAME_VECTOR=y
# CONFIG_GUP_BENCHMARK is not set
# CONFIG_READ_ONLY_THP_FOR_FS is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_PIN_MEMORY=y
# end of Memory Management options
CONFIG_NET=y
@@ -3282,6 +3283,7 @@ CONFIG_TCG_TIS_ST33ZP24_SPI=y
# CONFIG_RANDOM_TRUST_CPU is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+CONFIG_PIN_MEMORY_DEV=m
#
# I2C support
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c1f1fb9..5e282d3 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -50,6 +50,9 @@
#include <asm/efi.h>
#include <asm/xen/hypervisor.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
static int num_standard_resources;
static struct resource *standard_resources;
@@ -260,6 +263,12 @@ static void __init request_standard_resources(void)
quick_kexec_res.end <= res->end)
request_resource(res, &quick_kexec_res);
#endif
+#ifdef CONFIG_PIN_MEMORY
+ if (pin_memory_resource.end &&
+ pin_memory_resource.start >= res->start &&
+ pin_memory_resource.end <= res->end)
+ request_resource(res, &pin_memory_resource);
+#endif
}
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3e5a66..8ab5aac 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -42,6 +42,9 @@
#include <linux/sizes.h>
#include <asm/tlb.h>
#include <asm/alternative.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
#define ARM64_ZONE_DMA_BITS 30
@@ -78,6 +81,55 @@ static void __init reserve_crashkernel(void)
*/
#define MAX_USABLE_RANGES 2
+#ifdef CONFIG_PIN_MEMORY
+struct resource pin_memory_resource = {
+ .name = "Pin memory",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_RESERVED
+};
+
+static void __init reserve_pin_memory_res(void)
+{
+ unsigned long long mem_start, mem_len;
+ int ret;
+
+ ret = parse_pin_memory(boot_command_line, memblock_phys_mem_size(),
+ &mem_len, &mem_start);
+ if (ret || !mem_len)
+ return;
+
+ mem_len = PAGE_ALIGN(mem_len);
+
+ if (!memblock_is_region_memory(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region is not memory!\n");
+ return;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n");
+ return;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve for pin memory: base address is not 2MB aligned\n");
+ return;
+ }
+
+ memblock_reserve(mem_start, mem_len);
+ pr_debug("pin memory resource reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ mem_start, mem_start + mem_len, mem_len >> 20);
+
+ pin_memory_resource.start = mem_start;
+ pin_memory_resource.end = mem_start + mem_len - 1;
+}
+#else
+static void __init reserve_pin_memory_res(void)
+{
+}
+#endif /* CONFIG_PIN_MEMORY */
+
#ifdef CONFIG_CRASH_DUMP
static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
const char *uname, int depth, void *data)
@@ -455,6 +507,8 @@ void __init arm64_memblock_init(void)
reserve_park_mem();
#endif
+ reserve_pin_memory_res();
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
@@ -583,6 +637,12 @@ void __init mem_init(void)
/* this will put all unused low memory onto the freelists */
memblock_free_all();
+#ifdef CONFIG_PIN_MEMORY
+ /* pre alloc the pages for pin memory */
+ init_reserve_page_map((unsigned long)pin_memory_resource.start,
+ (unsigned long)(pin_memory_resource.end - pin_memory_resource.start + 1));
+#endif
+
mem_init_print_info(NULL);
/*
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index d229a2d..fbb94b8 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -496,3 +496,9 @@ config RANDOM_TRUST_BOOTLOADER
booloader is trustworthy so it will be added to the kernel's entropy
pool. Otherwise, say N here so it will be regarded as device input that
only mixes the entropy pool.
+
+config PIN_MEMORY_DEV
+ bool "/dev/pinmem character device"
+ default m
+ help
+ pin memory driver
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index ffce287..71d76fd 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
obj-$(CONFIG_ADI) += adi.o
+obj-$(CONFIG_PIN_MEMORY_DEV) += pin_memory.o
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
new file mode 100644
index 0000000..f46e056
--- /dev/null
+++ b/drivers/char/pin_memory.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright @ Huawei Technologies Co., Ltd. 2020-2020. ALL rights reserved.
+ * Description: Euler pin memory driver
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/mm_types.h>
+#include <linux/processor.h>
+#include <uapi/asm-generic/ioctl.h>
+#include <uapi/asm-generic/mman-common.h>
+#include <uapi/asm/setup.h>
+#include <linux/pin_mem.h>
+#include <linux/sched/mm.h>
+
+#define MAX_PIN_MEM_AREA_NUM 16
+struct _pin_mem_area {
+ unsigned long virt_start;
+ unsigned long virt_end;
+};
+
+struct pin_mem_area_set {
+ unsigned int pid;
+ unsigned int area_num;
+ struct _pin_mem_area mem_area[MAX_PIN_MEM_AREA_NUM];
+};
+
+#define PIN_MEM_MAGIC 0x59
+#define _SET_PIN_MEM_AREA 1
+#define _CLEAR_PIN_MEM_AREA 2
+#define _REMAP_PIN_MEM_AREA 3
+#define _FINISH_PIN_MEM_DUMP 4
+#define _PIN_MEM_IOC_MAX_NR 4
+#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
+#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
+#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+#define FINISH_PIN_MEM_DUMP _IOW(PIN_MEM_MAGIC, _FINISH_PIN_MEM_DUMP, int)
+static int set_pin_mem(struct pin_mem_area_set *pmas)
+{
+ int i;
+ int ret = 0;
+ struct _pin_mem_area *pma;
+ struct mm_struct *mm;
+ struct task_struct *task;
+ struct pid *pid_s;
+
+ pid_s = find_get_pid(pmas->pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pmas->pid);
+ return -EFAULT;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pmas->pid);
+ goto fail;
+ }
+ mm = get_task_mm(task);
+ for (i = 0; i < pmas->area_num; i++) {
+ pma = &(pmas->mem_area[i]);
+ ret = pin_mem_area(task, mm, pma->virt_start, pma->virt_end);
+ if (ret) {
+ mmput(mm);
+ goto fail;
+ }
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return ret;
+
+fail:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static int set_pin_mem_area(unsigned long arg)
+{
+ struct pin_mem_area_set pmas;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(pmas)))
+ return -EFAULT;
+ if (copy_from_user(&pmas, buf, sizeof(pmas)))
+ return -EINVAL;
+ if (pmas.area_num > MAX_PIN_MEM_AREA_NUM) {
+ pr_warn("Input area_num is too large.\n");
+ return -EINVAL;
+ }
+
+ return set_pin_mem(&pmas);
+}
+
+static int pin_mem_remap(unsigned long arg)
+{
+ int pid;
+ struct task_struct *task;
+ struct mm_struct *mm;
+ vm_fault_t ret;
+ void __user *buf = (void __user *)arg;
+ struct pid *pid_s;
+
+ if (!access_ok(buf, sizeof(int)))
+ return -EINVAL;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ return -EINVAL;
+
+ pid_s = find_get_pid(pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pid);
+ return -EINVAL;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pid);
+ goto fault;
+ }
+ mm = get_task_mm(task);
+ ret = do_mem_remap(pid, mm);
+ if (ret) {
+ pr_warn("Handle pin memory remap fail.\n");
+ mmput(mm);
+ goto fault;
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return 0;
+
+fault:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static long pin_memory_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret = 0;
+
+ if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
+ return -EINVAL;
+ if (_IOC_NR(cmd) > _PIN_MEM_IOC_MAX_NR)
+ return -EINVAL;
+
+ switch (cmd) {
+ case SET_PIN_MEM_AREA:
+ ret = set_pin_mem_area(arg);
+ break;
+ case CLEAR_PIN_MEM_AREA:
+ clear_pin_memory_record();
+ break;
+ case REMAP_PIN_MEM_AREA:
+ ret = pin_mem_remap(arg);
+ break;
+ case FINISH_PIN_MEM_DUMP:
+ ret = finish_pin_mem_dump();
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static const struct file_operations pin_memory_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pin_memory_ioctl,
+ .compat_ioctl = pin_memory_ioctl,
+};
+
+static struct miscdevice pin_memory_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pinmem",
+ .fops = &pin_memory_fops,
+};
+
+static int pin_memory_init(void)
+{
+ int err = misc_register(&pin_memory_miscdev);
+
+ if (!err)
+ pr_info("pin_memory init\n");
+ else
+ pr_warn("pin_memory init failed!\n");
+ return err;
+}
+
+static void pin_memory_exit(void)
+{
+ misc_deregister(&pin_memory_miscdev);
+ pr_info("pin_memory ko exists!\n");
+}
+
+module_init(pin_memory_init);
+module_exit(pin_memory_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Euler");
+MODULE_DESCRIPTION("pin memory");
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index fc0ef33..30f0df3 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -87,4 +87,9 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline, unsigned long long system_ram,
+ unsigned long long *pin_size, unsigned long long *pin_base);
+#endif
+
#endif /* LINUX_CRASH_CORE_H */
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
new file mode 100644
index 0000000..bc8b03e
--- /dev/null
+++ b/include/linux/pin_mem.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for check point and restore task.
+ */
+#ifndef _LINUX_PIN_MEMORY_H
+#define _LINUX_PIN_MEMORY_H
+
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/errno.h>
+#include <linux/mm_types.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARM64
+#include <linux/ioport.h>
+#endif
+
+#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)
+
+#define COLLECT_PAGES_FINISH 0
+#define COLLECT_PAGES_NEED_CONTINUE 1
+#define COLLECT_PAGES_FAIL -1
+
+#define COMPOUND_PAD_MASK 0xffffffff
+#define COMPOUND_PAD_START 0x88
+#define COMPOUND_PAD_DELTA 0x40
+#define LIST_POISON4 0xdead000000000400
+#define PAGE_FLAGS_CHECK_RESERVED (1UL << PG_reserved)
+#define SHA256_DIGEST_SIZE 32
+#define next_pme(pme) ((unsigned long *)(pme + 1) + pme->nr_pages)
+#define PIN_MEM_DUMP_MAGIC 0xfeab000000001acd
+struct page_map_entry {
+ unsigned long virt_addr;
+ unsigned int nr_pages;
+ unsigned int is_huge_page;
+ unsigned long redirect_start;
+ unsigned long phy_addr_array[0];
+};
+
+struct page_map_info {
+ int pid;
+ int pid_reserved;
+ unsigned int entry_num;
+ int disable_free_page;
+ struct page_map_entry *pme;
+};
+
+struct pin_mem_dump_info {
+ char sha_digest[SHA256_DIGEST_SIZE];
+ unsigned long magic;
+ unsigned int pin_pid_num;
+ struct page_map_info pmi_array[0];
+};
+
+struct redirect_info {
+ unsigned int redirect_pages;
+ unsigned int redirect_index[0];
+};
+
+extern struct page_map_info *get_page_map_info(int pid);
+extern struct page_map_info *create_page_map_info(int pid);
+extern vm_fault_t do_mem_remap(int pid, struct mm_struct *mm);
+extern vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern void clear_pin_memory_record(void);
+extern int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr);
+extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern int finish_pin_mem_dump(void);
+
+/* reserve space for pin memory*/
+#ifdef CONFIG_ARM64
+extern struct resource pin_memory_resource;
+#endif
+extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+
+#endif /* CONFIG_PIN_MEMORY */
+#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index bfed474..2407de3 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -450,6 +450,17 @@ void __init reserve_crashkernel(void)
}
#endif /* CONFIG_ARCH_WANT_RESERVE_CRASH_KERNEL */
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *pin_size,
+ unsigned long long *pin_base)
+{
+ return __parse_crashkernel(cmdline, system_ram, pin_size, pin_base,
+ "pinmemory=", NULL);
+}
+#endif
+
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
void *data, size_t data_len)
{
diff --git a/mm/Kconfig b/mm/Kconfig
index 390165f..930dc13 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -859,4 +859,12 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config PIN_MEMORY
+ bool "Support for pin memory"
+ depends on CHECKPOINT_RESTORE
+ help
+ Say y here to enable the pin memory feature for checkpoint
+ and restore. We can pin the memory data of tasks and collect
+ the corresponding physical pages mapping info in checkpoint,
+ and remap the physical pages to restore tasks in restore.
endmenu
diff --git a/mm/Makefile b/mm/Makefile
index d73aed0..4963827 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -120,3 +120,4 @@ obj-$(CONFIG_MEMFD_CREATE) += memfd.o
obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o
+obj-$(CONFIG_PIN_MEMORY) += pin_mem.o
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 0bc4a2c..8a11d30 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2996,3 +2996,64 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
update_mmu_cache_pmd(vma, address, pvmw->pmd);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ gfp_t gfp;
+ pgtable_t pgtable;
+ spinlock_t *ptl;
+ pmd_t entry;
+ vm_fault_t ret = 0;
+
+ if (unlikely(anon_vma_prepare(vma)))
+ return VM_FAULT_OOM;
+ if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
+ return VM_FAULT_OOM;
+ gfp = alloc_hugepage_direct_gfpmask(vma);
+ prep_transhuge_page(page);
+ if (mem_cgroup_charge(page, vma->vm_mm, gfp)) {
+ put_page(page);
+ count_vm_event(THP_FAULT_FALLBACK);
+ count_vm_event(THP_FAULT_FALLBACK_CHARGE);
+ return VM_FAULT_FALLBACK;
+ }
+ cgroup_throttle_swaprate(page, gfp);
+
+ pgtable = pte_alloc_one(vma->vm_mm);
+ if (unlikely(!pgtable)) {
+ ret = VM_FAULT_OOM;
+ goto release;
+ }
+ __SetPageUptodate(page);
+ ptl = pmd_lock(vma->vm_mm, pmd);
+ if (unlikely(!pmd_none(*pmd))) {
+ goto unlock_release;
+ } else {
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto unlock_release;
+ entry = mk_huge_pmd(page, vma->vm_page_prot);
+ entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+ page_add_new_anon_rmap(page, vma, address, true);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+ pgtable_trans_huge_deposit(vma->vm_mm, pmd, pgtable);
+ set_pmd_at(vma->vm_mm, address, pmd, entry);
+ add_mm_counter(vma->vm_mm, MM_ANONPAGES, HPAGE_PMD_NR);
+ mm_inc_nr_ptes(vma->vm_mm);
+ spin_unlock(ptl);
+ count_vm_event(THP_FAULT_ALLOC);
+ count_memcg_event_mm(vma->vm_mm, THP_FAULT_ALLOC);
+ }
+
+ return 0;
+unlock_release:
+ spin_unlock(ptl);
+release:
+ if (pgtable)
+ pte_free(vma->vm_mm, pgtable);
+ put_page(page);
+ return ret;
+}
+#endif
diff --git a/mm/memory.c b/mm/memory.c
index 50632c4..7b7f1a7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5248,3 +5248,62 @@ void ptlock_free(struct page *page)
kmem_cache_free(page_ptl_cachep, page->ptl);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ pte_t entry;
+ spinlock_t *ptl;
+ pte_t *pte;
+ vm_fault_t ret = 0;
+
+ if (pte_alloc(vma->vm_mm, pmd))
+ return VM_FAULT_OOM;
+
+ /* See the comment in pte_alloc_one_map() */
+ if (unlikely(pmd_trans_unstable(pmd)))
+ return 0;
+
+ /* Allocate our own private page. */
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+
+ if (mem_cgroup_charge(page, vma->vm_mm, GFP_KERNEL))
+ goto oom_free_page;
+ cgroup_throttle_swaprate(page, GFP_KERNEL);
+
+ __SetPageUptodate(page);
+
+ entry = mk_pte(page, vma->vm_page_prot);
+ if (vma->vm_flags & VM_WRITE)
+ entry = pte_mkwrite(pte_mkdirty(entry));
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, address,
+ &ptl);
+ if (!pte_none(*pte)) {
+ ret = VM_FAULT_FALLBACK;
+ goto release;
+ }
+
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto release;
+ inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
+ page_add_new_anon_rmap(page, vma, address, false);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+
+ set_pte_at(vma->vm_mm, address, pte, entry);
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, pte);
+unlock:
+ pte_unmap_unlock(pte, ptl);
+ return ret;
+release:
+ put_page(page);
+ goto unlock;
+oom_free_page:
+ put_page(page);
+oom:
+ return VM_FAULT_OOM;
+}
+#endif
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
new file mode 100644
index 0000000..0a143b6
--- /dev/null
+++ b/mm/pin_mem.c
@@ -0,0 +1,950 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for check point and restore task.
+ */
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched/cputime.h>
+#include <linux/tick.h>
+#include <linux/mm.h>
+#include <linux/pin_mem.h>
+#include <linux/idr.h>
+#include <linux/page-isolation.h>
+#include <linux/sched/mm.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <crypto/sha.h>
+
+#define MAX_PIN_PID_NUM 128
+static DEFINE_SPINLOCK(page_map_entry_lock);
+
+struct pin_mem_dump_info *pin_mem_dump_start;
+unsigned int pin_pid_num;
+static unsigned int *pin_pid_num_addr;
+static unsigned long __page_map_entry_start;
+static unsigned long page_map_entry_end;
+static struct page_map_info *user_space_reserve_start;
+static struct page_map_entry *page_map_entry_start;
+unsigned int max_pin_pid_num __read_mostly;
+unsigned long redirect_space_size;
+unsigned long redirect_space_start;
+#define DEFAULT_REDIRECT_SPACE_SIZE 0x100000
+
+static int __init setup_max_pin_pid_num(char *str)
+{
+ int ret = 0;
+
+ if (!str)
+ goto out;
+
+ ret = kstrtouint(str, 10, &max_pin_pid_num);
+out:
+ if (ret) {
+ pr_warn("Unable to parse max pin pid num.\n");
+ } else {
+ if (max_pin_pid_num > MAX_PIN_PID_NUM) {
+ max_pin_pid_num = 0;
+ pr_warn("Input max_pin_pid_num is too large.\n");
+ }
+ }
+ return ret;
+}
+early_param("max_pin_pid_num", setup_max_pin_pid_num);
+
+static int __init setup_redirect_space_size(char *str)
+{
+ if (!str)
+ goto out;
+
+ redirect_space_size = memparse(str, NULL);
+out:
+ if (!redirect_space_size) {
+ pr_warn("Unable to parse redirect space size, use the default value.\n");
+ redirect_space_size = DEFAULT_REDIRECT_SPACE_SIZE;
+ }
+ return 0;
+}
+early_param("redirect_space_size", setup_redirect_space_size);
+
+struct page_map_info *create_page_map_info(int pid)
+{
+ struct page_map_info *new;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ if (pin_pid_num >= max_pin_pid_num) {
+ pr_warn("Pin pid num too large than max_pin_pid_num, fail create: %d!", pid);
+ return NULL;
+ }
+ new = (struct page_map_info *)(user_space_reserve_start + pin_pid_num);
+ new->pid = pid;
+ new->pme = NULL;
+ new->entry_num = 0;
+ new->pid_reserved = false;
+ new->disable_free_page = false;
+ (*pin_pid_num_addr)++;
+ pin_pid_num++;
+ return new;
+}
+EXPORT_SYMBOL_GPL(create_page_map_info);
+
+struct page_map_info *get_page_map_info(int pid)
+{
+ int i;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ for (i = 0; i < pin_pid_num; i++) {
+ if (user_space_reserve_start[i].pid == pid)
+ return &(user_space_reserve_start[i]);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(get_page_map_info);
+
+static struct page *find_head_page(struct page *page)
+{
+ struct page *p = page;
+
+ while (!PageBuddy(p)) {
+ if (PageLRU(p))
+ return NULL;
+ p--;
+ }
+ return p;
+}
+
+static void spilt_page_area_left(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ unsigned long total_size = 0;
+
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ list_add(&page[total_size].lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(page[total_size]._mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(&page[total_size], order);
+ set_pageblock_migratetype(&page[total_size], MIGRATE_MOVABLE);
+ area->nr_free++;
+ total_size += cur_size;
+ size -= cur_size;
+ }
+ }
+}
+
+static void spilt_page_area_right(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ struct page *right_page, *head_page;
+
+ right_page = page + size;
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ head_page = right_page - cur_size;
+ list_add(&head_page->lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(head_page->_mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(head_page, order);
+ set_pageblock_migratetype(head_page, MIGRATE_MOVABLE);
+ area->nr_free++;
+ size -= cur_size;
+ right_page = head_page;
+ }
+ }
+}
+
+void reserve_page_from_buddy(unsigned long nr_pages, struct page *page)
+{
+ unsigned int current_order;
+ struct page *page_end;
+ struct free_area *area;
+ struct zone *zone;
+ struct page *head_page;
+
+ head_page = find_head_page(page);
+ if (!head_page) {
+ pr_warn("Find page head fail.");
+ return;
+ }
+ current_order = head_page->private;
+ page_end = head_page + (1 << current_order);
+ zone = page_zone(head_page);
+ area = &(zone->free_area[current_order]);
+ list_del(&head_page->lru);
+ atomic_set(&head_page->_mapcount, -1);
+ set_page_private(head_page, 0);
+ area->nr_free--;
+ if (head_page != page)
+ spilt_page_area_left(zone, area, head_page,
+ (unsigned long)(page - head_page), current_order);
+ page = page + nr_pages;
+ if (page < page_end) {
+ spilt_page_area_right(zone, area, page,
+ (unsigned long)(page_end - page), current_order);
+ } else if (page > page_end) {
+ pr_warn("Find page end smaller than page.");
+ }
+}
+
+static inline void reserve_user_normal_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy(1, page);
+}
+
+static void init_huge_pmd_pages(struct page *head_page)
+{
+ int i = 0;
+ struct page *page = head_page;
+
+ __set_bit(PG_head, &page->flags);
+ __set_bit(PG_active, &page->flags);
+ atomic_set(&page->_refcount, 1);
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ page->compound_dtor = HUGETLB_PAGE_DTOR + 1;
+ page->compound_order = HPAGE_PMD_ORDER;
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ i++;
+ INIT_LIST_HEAD(&(page->deferred_list));
+ for (; i < HPAGE_PMD_NR; i++) {
+ page = head_page + i;
+ page->compound_head = (unsigned long)head_page + 1;
+ }
+}
+
+static inline void reserve_user_huge_pmd_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy((1 << HPAGE_PMD_ORDER), page);
+ init_huge_pmd_pages(page);
+}
+
+int reserve_user_map_pages_fail;
+
+void free_user_map_pages(unsigned int pid_index, unsigned int entry_index, unsigned int page_index)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ for (index = 0; index < pid_index; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < entry_index; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ for (j = 0; j < page_index; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+}
+
+bool check_redirect_end_valid(struct redirect_info *redirect_start,
+ unsigned long max_redirect_page_num)
+{
+ unsigned long redirect_end;
+
+ redirect_end = ((unsigned long)(redirect_start + 1) +
+ max_redirect_page_num * sizeof(unsigned int));
+ if (redirect_end > redirect_space_start + redirect_space_size)
+ return false;
+ return false;
+}
+
+static void reserve_user_space_map_pages(void)
+{
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned int i, j, index;
+ struct page *page;
+ unsigned long flags;
+ unsigned long phy_addr;
+ unsigned long redirect_pages = 0;
+ struct redirect_info *redirect_start = (struct redirect_info *)redirect_space_start;
+
+ if (!user_space_reserve_start || !redirect_start)
+ return;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ redirect_pages = 0;
+ if (!check_redirect_end_valid(redirect_start, pme->nr_pages))
+ redirect_start = NULL;
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (atomic_read(&page->_refcount)) {
+ if ((page->flags & PAGE_FLAGS_CHECK_RESERVED)
+ && !pme->redirect_start)
+ pme->redirect_start =
+ (unsigned long)redirect_start;
+ if (redirect_start &&
+ (page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ redirect_start->redirect_index[redirect_pages] = j;
+ redirect_pages++;
+ continue;
+ } else {
+ reserve_user_map_pages_fail = 1;
+ pr_warn("Page %pK refcount %d large than zero, no need reserve.\n",
+ page, atomic_read(&page->_refcount));
+ goto free_pages;
+ }
+ }
+ if (!pme->is_huge_page)
+ reserve_user_normal_pages(page);
+ else
+ reserve_user_huge_pmd_pages(page);
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ if (redirect_pages && redirect_start) {
+ redirect_start->redirect_pages = redirect_pages;
+ redirect_start = (struct redirect_info *)(
+ (unsigned long)(redirect_start + 1) +
+ redirect_start->redirect_pages * sizeof(unsigned int));
+ }
+ }
+ }
+ spin_unlock(&page_map_entry_lock);
+ return;
+free_pages:
+ free_user_map_pages(index, i, j);
+ spin_unlock(&page_map_entry_lock);
+}
+
+
+int calculate_pin_mem_digest(struct pin_mem_dump_info *pmdi, char *digest)
+{
+ int i;
+ struct sha256_state sctx;
+
+ if (!digest)
+ digest = pmdi->sha_digest;
+ sha256_init(&sctx);
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->magic)),
+ sizeof(struct pin_mem_dump_info) - SHA256_DIGEST_SIZE);
+ for (i = 0; i < pmdi->pin_pid_num; i++) {
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->pmi_array[i])),
+ sizeof(struct page_map_info));
+ }
+ sha256_final(&sctx, digest);
+ return 0;
+}
+
+static int check_sha_digest(struct pin_mem_dump_info *pmdi)
+{
+ int ret = 0;
+ char digest[SHA256_DIGEST_SIZE] = {0};
+
+ ret = calculate_pin_mem_digest(pmdi, digest);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ if (memcmp(pmdi->sha_digest, digest, SHA256_DIGEST_SIZE)) {
+ pr_warn("pin mem dump info sha256 digest match error!\n");
+ return -EFAULT;
+ }
+ return ret;
+}
+
+/*
+ * The whole page map entry collect process must be Sequentially.
+ * The user_space_reserve_start points to the first page map info for
+ * the first dump task. And the page_map_entry_start points to
+ * the first page map entry of the first dump vma.
+ */
+static void init_page_map_info(struct pin_mem_dump_info *pmdi, unsigned long map_len)
+{
+ if (pin_mem_dump_start || !max_pin_pid_num) {
+ pr_warn("pin page map already init or max_pin_pid_num not set.\n");
+ return;
+ }
+ if (map_len < sizeof(struct pin_mem_dump_info) +
+ max_pin_pid_num * sizeof(struct page_map_info) + redirect_space_size) {
+ pr_warn("pin memory reserved memblock too small.\n");
+ return;
+ }
+ if ((pmdi->magic != PIN_MEM_DUMP_MAGIC) || (pmdi->pin_pid_num > max_pin_pid_num) ||
+ check_sha_digest(pmdi))
+ memset(pmdi, 0, sizeof(struct pin_mem_dump_info));
+ pin_mem_dump_start = pmdi;
+ pin_pid_num = pmdi->pin_pid_num;
+ pr_info("pin_pid_num: %d\n", pin_pid_num);
+ pin_pid_num_addr = &(pmdi->pin_pid_num);
+ user_space_reserve_start =
+ (struct page_map_info *)pmdi->pmi_array;
+ page_map_entry_start =
+ (struct page_map_entry *)(user_space_reserve_start + max_pin_pid_num);
+ page_map_entry_end = (unsigned long)pmdi + map_len - redirect_space_size;
+ redirect_space_start = page_map_entry_end;
+ if (pin_pid_num > 0)
+ reserve_user_space_map_pages();
+}
+
+int finish_pin_mem_dump(void)
+{
+ int ret;
+
+ pin_mem_dump_start->magic = PIN_MEM_DUMP_MAGIC;
+ memset(pin_mem_dump_start->sha_digest, 0, SHA256_DIGEST_SIZE);
+ ret = calculate_pin_mem_digest(pin_mem_dump_start, NULL);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ return ret;
+}
+
+int collect_pmd_huge_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ long res;
+ int index = 0;
+ unsigned long start = start_addr;
+ struct page *temp_page;
+
+ while (start < end_addr) {
+ temp_page = NULL;
+ res = get_user_pages_remote(task->mm, start, 1,
+ FOLL_TOUCH | FOLL_GET, &temp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get huge page for addr(%lx) fail.", start);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(temp_page)) {
+ start += HPAGE_PMD_SIZE;
+ pme->phy_addr_array[index] = page_to_phys(temp_page);
+ index++;
+ } else {
+ pme->nr_pages = index;
+ atomic_dec(&((temp_page)->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ }
+ pme->nr_pages = index;
+ return COLLECT_PAGES_FINISH;
+}
+
+int collect_normal_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ int res;
+ unsigned long next;
+ unsigned long i, nr_pages;
+ struct page *tmp_page;
+ unsigned long *phy_addr_array = pme->phy_addr_array;
+ struct page **page_array = (struct page **)pme->phy_addr_array;
+
+ next = (start_addr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
+ next = (next > end_addr) ? end_addr : next;
+ pme->nr_pages = 0;
+ while (start_addr < next) {
+ nr_pages = (PAGE_ALIGN(next) - start_addr) / PAGE_SIZE;
+ res = get_user_pages_remote(task->mm, start_addr, 1,
+ FOLL_TOUCH | FOLL_GET, &tmp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user page of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(tmp_page)) {
+ atomic_dec(&(tmp_page->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ atomic_dec(&(tmp_page->_refcount));
+ if (PageTail(tmp_page)) {
+ start_addr = next;
+ pme->virt_addr = start_addr;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ?
+ end_addr : (next + HPAGE_PMD_SIZE);
+ continue;
+ }
+ res = get_user_pages_remote(task->mm, start_addr, nr_pages,
+ FOLL_TOUCH | FOLL_GET, page_array, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user pages of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ for (i = 0; i < nr_pages; i++)
+ phy_addr_array[i] = page_to_phys(page_array[i]);
+ pme->nr_pages += nr_pages;
+ page_array += nr_pages;
+ phy_addr_array += nr_pages;
+ start_addr = next;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ? end_addr : (next + HPAGE_PMD_SIZE);
+ }
+ return COLLECT_PAGES_FINISH;
+}
+
+/* Users make sure that the pin memory belongs to anonymous vma. */
+int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr)
+{
+ int pid, ret;
+ int is_huge_page = false;
+ unsigned int page_size;
+ unsigned long nr_pages, flags;
+ struct page_map_entry *pme;
+ struct page_map_info *pmi;
+ struct vm_area_struct *vma;
+ unsigned long i;
+ struct page *tmp_page;
+
+ if (!page_map_entry_start
+ || !task || !mm
+ || start_addr >= end_addr)
+ return -EFAULT;
+
+ pid = task->pid;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ nr_pages = ((end_addr - start_addr) / PAGE_SIZE);
+ if ((unsigned long)page_map_entry_start + nr_pages * sizeof(struct page *) >=
+ page_map_entry_end) {
+ pr_warn("Page map entry use up!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ vma = find_extend_vma(mm, start_addr);
+ if (!vma) {
+ pr_warn("Find no match vma!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (start_addr == (start_addr & HPAGE_PMD_MASK) &&
+ transparent_hugepage_enabled(vma)) {
+ page_size = HPAGE_PMD_SIZE;
+ is_huge_page = true;
+ } else {
+ page_size = PAGE_SIZE;
+ }
+ pme = page_map_entry_start;
+ pme->virt_addr = start_addr;
+ pme->redirect_start = 0;
+ pme->is_huge_page = is_huge_page;
+ memset(pme->phy_addr_array, 0, nr_pages * sizeof(unsigned long));
+ down_write(&mm->mmap_lock);
+ if (!is_huge_page) {
+ ret = collect_normal_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = true;
+ page_size = HPAGE_PMD_SIZE;
+ ret = collect_pmd_huge_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ } else {
+ ret = collect_pmd_huge_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = false;
+ page_size = PAGE_SIZE;
+ ret = collect_normal_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ }
+ up_write(&mm->mmap_lock);
+ if (ret == COLLECT_PAGES_FAIL) {
+ ret = -EFAULT;
+ goto finish;
+ }
+
+ /* check for zero pages */
+ for (i = 0; i < pme->nr_pages; i++) {
+ tmp_page = phys_to_page(pme->phy_addr_array[i]);
+ if (!pme->is_huge_page) {
+ if (page_to_pfn(tmp_page) == my_zero_pfn(pme->virt_addr + i * PAGE_SIZE))
+ pme->phy_addr_array[i] = 0;
+ } else if (is_huge_zero_page(tmp_page))
+ pme->phy_addr_array[i] = 0;
+ }
+
+ page_map_entry_start = (struct page_map_entry *)(next_pme(pme));
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ pmi = create_page_map_info(pid);
+ if (!pmi) {
+ pr_warn("Create page map info fail for pid: %d!\n", pid);
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (!pmi->pme)
+ pmi->pme = pme;
+ pmi->entry_num++;
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ if (ret == COLLECT_PAGES_NEED_CONTINUE)
+ ret = pin_mem_area(task, mm, pme->virt_addr + pme->nr_pages * page_size, end_addr);
+ return ret;
+finish:
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pin_mem_area);
+
+vm_fault_t remap_normal_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * PAGE_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (page_to_pfn(page) == my_zero_pfn(address)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ new = alloc_zeroed_user_highpage_movable(vma, address);
+ if (!new) {
+ pr_warn("Redirect alloc page fail\n");
+ continue;
+ }
+ copy_page(page_to_virt(new), phys_to_virt(phy_addr));
+ page = new;
+ redirect_pages++;
+ }
+ page->mapping = NULL;
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ __free_page(phys_to_page(phy_addr));
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ return ret;
+}
+
+static inline gfp_t get_hugepage_gfpmask(struct vm_area_struct *vma)
+{
+ const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ __GFP_KSWAPD_RECLAIM);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ 0);
+ return GFP_TRANSHUGE_LIGHT;
+}
+
+vm_fault_t remap_huge_pmd_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ gfp_t gfp;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * HPAGE_PMD_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (is_huge_zero_page(page)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ gfp = get_hugepage_gfpmask(vma);
+ new = alloc_hugepage_vma(gfp, vma, address, HPAGE_PMD_ORDER);
+ if (!new) {
+ pr_warn("Redirect alloc huge page fail\n");
+ continue;
+ }
+ memcpy(page_to_virt(new), phys_to_virt(phy_addr), HPAGE_PMD_SIZE);
+ page = new;
+ redirect_pages++;
+ }
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_huge_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, HPAGE_PMD_ORDER);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ return ret;
+}
+
+static void free_unmap_pages(struct page_map_info *pmi,
+ struct page_map_entry *pme,
+ unsigned int index)
+{
+ unsigned int i, j;
+ unsigned long phy_addr;
+ unsigned int order;
+ struct page *page;
+
+ pme = (struct page_map_entry *)(next_pme(pme));
+ for (i = index; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ }
+}
+
+vm_fault_t do_mem_remap(int pid, struct mm_struct *mm)
+{
+ unsigned int i = 0;
+ vm_fault_t ret = 0;
+ struct vm_area_struct *vma;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned long flags;
+
+ if (reserve_user_map_pages_fail)
+ return -EFAULT;
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ return -EFAULT;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ pmi->disable_free_page = true;
+ spin_unlock(&page_map_entry_lock);
+ down_write(&mm->mmap_lock);
+ pme = pmi->pme;
+ vma = mm->mmap;
+ while ((i < pmi->entry_num) && (vma != NULL)) {
+ if (pme->virt_addr >= vma->vm_start && pme->virt_addr < vma->vm_end) {
+ i++;
+ if (!vma_is_anonymous(vma)) {
+ pme = (struct page_map_entry *)(next_pme(pme));
+ continue;
+ }
+ if (!pme->is_huge_page) {
+ ret = remap_normal_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ } else {
+ ret = remap_huge_pmd_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ } else {
+ vma = vma->vm_next;
+ }
+ }
+ up_write(&mm->mmap_lock);
+ return 0;
+free:
+ free_unmap_pages(pmi, pme, i);
+ up_write(&mm->mmap_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(do_mem_remap);
+
+#if defined(CONFIG_ARM64)
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+ void *addr;
+
+ if (!map_addr || !map_size)
+ return;
+ addr = phys_to_virt(map_addr);
+ init_page_map_info((struct pin_mem_dump_info *)addr, map_size);
+}
+#else
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+}
+#endif
+
+static void free_all_reserved_pages(void)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ if (!user_space_reserve_start || reserve_user_map_pages_fail)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->disable_free_page)
+ continue;
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+}
+
+/* Clear all pin memory record. */
+void clear_pin_memory_record(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ free_all_reserved_pages();
+ if (pin_pid_num_addr) {
+ *pin_pid_num_addr = 0;
+ pin_pid_num = 0;
+ page_map_entry_start = (struct page_map_entry *)__page_map_entry_start;
+ }
+ spin_unlock(&page_map_entry_lock);
+}
+EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+
+#endif /* CONFIG_PIN_MEMORY */
--
2.9.5
1
1
[PATCH OLK-5.10 v1] arm64: Declare var of local_cpu_stop only on PARK
by sangyan@huawei.com 01 Mar '21
by sangyan@huawei.com 01 Mar '21
01 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
Fix compile warning: unused variable 'ops' 'cpu'
while CONFIG_ARM64_CPU_PARK=n.
Put declaration of 'ops' and 'cpu' under
CONFIG_ARM64_CPU_PARK in local_cpu_stop.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/kernel/smp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 644bbd7..d7b750a 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -1024,8 +1024,10 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
int cpu;
const struct cpu_operations *ops = NULL;
+#endif
set_cpu_online(smp_processor_id(), false);
--
2.9.5
1
0
26 Feb '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
Introducing a feature of CPU PARK in order to save time
of cpus down and up during kexec, which may cost 250ms of
per cpu's down and 30ms of up.
As a result, for 128 cores, it costs more than 30 seconds
to down and up cpus during kexec. Think about 256 cores and more.
CPU PARK is a state that cpu power-on and staying in spin loop, polling
for exit chances, such as writing exit address.
Reserving a block of memory, to fill with cpu park text section,
exit address and park-magic-flag of each cpu. In implementation,
reserved one page for one cpu core.
Cpus going to park state instead of down in machine_shutdown().
Cpus going out of park state in smp_init instead of brought up.
One of cpu park sections in pre-reserved memory blocks,:
+--------------+
+ exit address +
+--------------+
+ park magic +
+--------------+
+ park codes +
+ . +
+ . +
+ . +
+--------------+
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/Kconfig | 12 ++
arch/arm64/include/asm/kexec.h | 6 +
arch/arm64/include/asm/smp.h | 15 +++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/cpu-park.S | 59 ++++++++++
arch/arm64/kernel/machine_kexec.c | 2 +-
arch/arm64/kernel/process.c | 4 +
arch/arm64/kernel/smp.c | 230 ++++++++++++++++++++++++++++++++++++++
arch/arm64/mm/init.c | 55 +++++++++
9 files changed, 383 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/cpu-park.S
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b9c5654..0885668 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -345,6 +345,18 @@ config KASAN_SHADOW_OFFSET
default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
+config ARM64_CPU_PARK
+ bool "Support CPU PARK on kexec"
+ depends on SMP
+ depends on KEXEC_CORE
+ help
+ This enables support for CPU PARK feature in
+ order to save time of cpu down to up.
+ CPU park is a state through kexec, spin loop
+ instead of cpu die before jumping to new kernel,
+ jumping out from loop to new kernel entry in
+ smp_init.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 79909ae..a133889 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -36,6 +36,11 @@
#define CRASH_ADDR_HIGH_MAX MEMBLOCK_ALLOC_ACCESSIBLE
+#ifdef CONFIG_ARM64_CPU_PARK
+/* CPU park state flag: "park" */
+#define PARK_MAGIC 0x7061726b
+#endif
+
#ifndef __ASSEMBLY__
/**
@@ -104,6 +109,7 @@ static inline void crash_post_resume(void) {}
#ifdef CONFIG_KEXEC_CORE
extern void __init reserve_crashkernel(void);
#endif
+void machine_kexec_mask_interrupts(void);
#ifdef CONFIG_KEXEC_FILE
#define ARCH_HAS_KIMAGE_ARCH
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 2e7f529..8c5d2d6 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -145,6 +145,21 @@ bool cpus_are_stuck_in_kernel(void);
extern void crash_smp_send_stop(void);
extern bool smp_crash_stop_failed(void);
+#ifdef CONFIG_ARM64_CPU_PARK
+#define PARK_SECTION_SIZE 1024
+struct cpu_park_info {
+ /* Physical address of reserved park memory. */
+ unsigned long start;
+ /* park reserve mem len should be PARK_SECTION_SIZE * NR_CPUS */
+ unsigned long len;
+ /* Virtual address of reserved park memory. */
+ unsigned long start_v;
+};
+extern struct cpu_park_info park_info;
+extern void enter_cpu_park(unsigned long text, unsigned long exit);
+extern void do_cpu_park(unsigned long exit);
+extern int kexec_smp_send_park(void);
+#endif
#endif /* ifndef __ASSEMBLY__ */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2621d5c..60478d2 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \
cpu-reset.o
+obj-$(CONFIG_ARM64_CPU_PARK) += cpu-park.o
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o
arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
diff --git a/arch/arm64/kernel/cpu-park.S b/arch/arm64/kernel/cpu-park.S
new file mode 100644
index 0000000..10c685c
--- /dev/null
+++ b/arch/arm64/kernel/cpu-park.S
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * CPU park routines
+ *
+ * Copyright (C) 2020 Huawei Technologies., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/sysreg.h>
+#include <asm/virt.h>
+
+.text
+.pushsection .idmap.text, "awx"
+
+/* cpu park helper in idmap section */
+SYM_CODE_START(enter_cpu_park)
+ /* Clear sctlr_el1 flags. */
+ mrs x12, sctlr_el1
+ mov_q x13, SCTLR_ELx_FLAGS
+ bic x12, x12, x13
+ pre_disable_mmu_workaround
+ msr sctlr_el1, x12 /* disable mmu */
+ isb
+
+ mov x18, x0
+ mov x0, x1 /* secondary_entry addr */
+ br x18 /* call do_cpu_park of each cpu */
+SYM_CODE_END(enter_cpu_park)
+
+.popsection
+
+SYM_CODE_START(do_cpu_park)
+ ldr x18, =PARK_MAGIC /* magic number "park" */
+ add x1, x0, #8
+ str x18, [x1] /* set on-park flag */
+ dc civac, x1 /* flush cache of "park" */
+ dsb nsh
+ isb
+
+.Lloop:
+ wfe
+ isb
+ ldr x19, [x0]
+ cmp x19, #0 /* test secondary_entry */
+ b.eq .Lloop
+
+ ic iallu /* invalidate the local I-cache */
+ dsb nsh
+ isb
+
+ br x19 /* jump to secondary_entry */
+SYM_CODE_END(do_cpu_park)
+
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index a0b144c..f47ce96 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -213,7 +213,7 @@ void machine_kexec(struct kimage *kimage)
BUG(); /* Should never get here. */
}
-static void machine_kexec_mask_interrupts(void)
+void machine_kexec_mask_interrupts(void)
{
unsigned int i;
struct irq_desc *desc;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 73e3b32..10cffee 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -146,6 +146,10 @@ void arch_cpu_idle_dead(void)
*/
void machine_shutdown(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (kexec_smp_send_park() == 0)
+ return;
+#endif
smp_shutdown_nonboot_cpus(reboot_cpu);
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 18e9727..dea67d0 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -32,6 +32,7 @@
#include <linux/irq_work.h>
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
+
#include <linux/kvm_host.h>
#include <asm/alternative.h>
@@ -93,6 +94,167 @@ static inline int op_cpu_kill(unsigned int cpu)
}
#endif
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_section {
+ unsigned long exit; /* exit address of park look */
+ unsigned long magic; /* maigc represent park state */
+ char text[0]; /* text section of park */
+};
+
+static int mmap_cpu_park_mem(void)
+{
+ if (!park_info.start)
+ return -ENOMEM;
+
+ if (park_info.start_v)
+ return 0;
+
+ park_info.start_v = (unsigned long)__ioremap(park_info.start,
+ park_info.len,
+ PAGE_KERNEL_EXEC);
+ if (!park_info.start_v) {
+ pr_warn("map park memory failed.");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline unsigned long cpu_park_section_v(unsigned int cpu)
+{
+ return park_info.start_v + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+static inline unsigned long cpu_park_section_p(unsigned int cpu)
+{
+ return park_info.start + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+/*
+ * Write the secondary_entry to exit section of park state.
+ * Then the secondary cpu will jump straight into the kernel
+ * by the secondary_entry.
+ */
+static int write_park_exit(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_text;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_exit = &park_section->exit;
+ park_text = (unsigned long *)park_section->text;
+ pr_debug("park_text 0x%lx : 0x%lx, do_cpu_park text 0x%lx : 0x%lx",
+ (unsigned long)park_text, *park_text,
+ (unsigned long)do_cpu_park,
+ *(unsigned long *)do_cpu_park);
+
+ /*
+ * Test first 8 bytes to determine
+ * whether needs to write cpu park exit.
+ */
+ if (*park_text == *(unsigned long *)do_cpu_park) {
+ writeq_relaxed(__pa_symbol(secondary_entry), park_exit);
+ __flush_dcache_area((__force void *)park_exit,
+ sizeof(unsigned long));
+ flush_icache_range((unsigned long)park_exit,
+ (unsigned long)(park_exit + 1));
+ sev();
+ dsb(sy);
+ isb();
+
+ pr_debug("Write cpu %u secondary entry 0x%lx to 0x%lx.",
+ cpu, *park_exit, (unsigned long)park_exit);
+ pr_info("Boot cpu %u from PARK state.", cpu);
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+/* Install cpu park sections for the specific cpu. */
+static int install_cpu_park(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_magic;
+ unsigned long park_text_len;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ pr_debug("Install cpu park on cpu %u park exit 0x%lx park text 0x%lx",
+ cpu, (unsigned long)park_section,
+ (unsigned long)(park_section->text));
+
+ park_exit = &park_section->exit;
+ park_magic = &park_section->magic;
+ park_text_len = PARK_SECTION_SIZE - sizeof(struct cpu_park_section);
+
+ *park_exit = 0UL;
+ *park_magic = 0UL;
+ memcpy((void *)park_section->text, do_cpu_park, park_text_len);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int uninstall_cpu_park(unsigned int cpu)
+{
+ unsigned long park_section;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = cpu_park_section_v(cpu);
+ memset((void *)park_section, 0, PARK_SECTION_SIZE);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int cpu_wait_park(unsigned int cpu)
+{
+ long timeout;
+ struct cpu_park_section *park_section;
+
+ volatile unsigned long *park_magic;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_magic = &park_section->magic;
+
+ timeout = USEC_PER_SEC;
+ while (*park_magic != PARK_MAGIC && timeout--)
+ udelay(1);
+
+ if (timeout > 0)
+ pr_debug("cpu %u park done.", cpu);
+ else
+ pr_err("cpu %u park failed.", cpu);
+
+ return *park_magic == PARK_MAGIC;
+}
+
+static void cpu_park(unsigned int cpu)
+{
+ unsigned long park_section_p;
+ unsigned long park_exit_phy;
+ unsigned long do_park;
+ typeof(enter_cpu_park) *park;
+
+ park_section_p = cpu_park_section_p(cpu);
+ park_exit_phy = park_section_p;
+ pr_debug("Go to park cpu %u exit address 0x%lx", cpu, park_exit_phy);
+
+ do_park = park_section_p + sizeof(struct cpu_park_section);
+ park = (void *)__pa_symbol(enter_cpu_park);
+
+ cpu_install_idmap();
+ park(do_park, park_exit_phy);
+ unreachable();
+}
+#endif
/*
* Boot a secondary CPU, and assign it the specified idle task.
@@ -102,6 +264,10 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle)
{
const struct cpu_operations *ops = get_cpu_ops(cpu);
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (write_park_exit(cpu) == 0)
+ return 0;
+#endif
if (ops->cpu_boot)
return ops->cpu_boot(cpu);
@@ -131,6 +297,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
@@ -844,10 +1013,32 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
+ int cpu;
+ const struct cpu_operations *ops = NULL;
+#endif
+
set_cpu_online(smp_processor_id(), false);
local_daif_mask();
sdei_mask_local_cpu();
+
+#ifdef CONFIG_ARM64_CPU_PARK
+ /*
+ * Go to cpu park state.
+ * Otherwise go to cpu die.
+ */
+ cpu = smp_processor_id();
+ if (kexec_in_progress && park_info.start_v) {
+ machine_kexec_mask_interrupts();
+ cpu_park(cpu);
+
+ ops = get_cpu_ops(cpu);
+ if (ops && ops->cpu_die)
+ ops->cpu_die(cpu);
+ }
+#endif
+
cpu_park_loop();
}
@@ -1053,6 +1244,45 @@ void smp_send_stop(void)
sdei_mask_local_cpu();
}
+#ifdef CONFIG_ARM64_CPU_PARK
+int kexec_smp_send_park(void)
+{
+ unsigned long cpu;
+
+ if (WARN_ON(!kexec_in_progress)) {
+ pr_crit("%s called not in kexec progress.", __func__);
+ return -EPERM;
+ }
+
+ if (mmap_cpu_park_mem() != 0) {
+ pr_info("no cpuparkmem, goto normal way.");
+ return -EPERM;
+ }
+
+ local_irq_disable();
+
+ if (num_online_cpus() > 1) {
+ cpumask_t mask;
+
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+
+ for_each_cpu(cpu, &mask)
+ install_cpu_park(cpu);
+ smp_cross_call(&mask, IPI_CPU_STOP);
+
+ /* Wait for other CPUs to park */
+ for_each_cpu(cpu, &mask)
+ cpu_wait_park(cpu);
+ pr_info("smp park other cpus done\n");
+ }
+
+ sdei_mask_local_cpu();
+
+ return 0;
+}
+#endif
+
#ifdef CONFIG_KEXEC_CORE
void crash_smp_send_stop(void)
{
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 794f992..d01259c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -236,6 +236,57 @@ static void __init fdt_enforce_memory_region(void)
memblock_add(usable_rgns[1].base, usable_rgns[1].size);
}
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_info park_info = {
+ .start = 0,
+ .len = PARK_SECTION_SIZE * NR_CPUS,
+ .start_v = 0,
+};
+
+static int __init parse_park_mem(char *p)
+{
+ if (!p)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(memparse(p, NULL));
+ if (park_info.start == 0)
+ pr_info("cpu park mem params[%s]", p);
+
+ return 0;
+}
+early_param("cpuparkmem", parse_park_mem);
+
+static int __init reserve_park_mem(void)
+{
+ if (park_info.start == 0 || park_info.len == 0)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(park_info.start);
+ park_info.len = PAGE_ALIGN(park_info.len);
+
+ if (!memblock_is_region_memory(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region is not memory!");
+ goto out;
+ }
+
+ if (memblock_is_region_reserved(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region overlaps reserved memory!");
+ goto out;
+ }
+
+ memblock_remove(park_info.start, park_info.len);
+ pr_info("cpu park mem reserved: 0x%016lx - 0x%016lx (%ld MB)",
+ park_info.start, park_info.start + park_info.len,
+ park_info.len >> 20);
+
+ return 0;
+out:
+ park_info.start = 0;
+ park_info.len = 0;
+ return -EINVAL;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -357,6 +408,10 @@ void __init arm64_memblock_init(void)
reserve_crashkernel();
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
--
2.9.5
1
1
MPAM bugfix @ 20210224
James Morse (10):
arm64/mpam: Add mpam driver discovery phase and kbuild boiler plate
cacheinfo: Provide a helper to find a cacheinfo leaf
arm64/mpam: Probe supported partid/pmg ranges from devices
arm64/mpam: Supplement MPAM MSC register layout definitions
arm64/mpam: Probe the features resctrl supports
arm64/mpam: Reset controls when CPUs come online
arm64/mpam: Summarize feature support during mpam_enable()
arm64/mpam: resctrl: Re-synchronise resctrl's view of online CPUs
drivers: base: cacheinfo: Add helper to search cacheinfo by of_node
arm64/mpam: Enabling registering and logging error interrupts
Wang ShaoBo (55):
arm64/mpam: Preparing for MPAM refactoring
arm64/mpam: Add helper for getting mpam sysprops
arm64/mpam: Allocate mpam component configuration arrays
arm64/mpam: Pick MPAM resources and events for resctrl_res exported
arm64/mpam: Init resctrl resources' info from resctrl_res selected
arm64/mpam: resctrl: Handle cpuhp and resctrl_dom allocation
arm64/mpam: Implement helpers for handling configuration and
monitoring
arm64/mpam: Migrate old MSCs' discovery process to new branch
arm64/mpam: Add helper for getting MSCs' configuration
arm64/mpam: Probe partid,pmg and feature capabilities' ranges from
classes
arm64/mpam: resctrl: Rebuild configuration and monitoring pipeline
arm64/mpam: resctrl: Append schemata CDP definitions
arm64/mpam: resctrl: Supplement cdpl2,cdpl3 for mount options
arm64/mpam: resctrl: Add helpers for init and destroy schemata list
arm64/mpam: resctrl: Use resctrl_group_init_alloc() to init schema
list
arm64/mpam: resctrl: Write and read schemata by schema_list
arm64/mpam: Support cdp in mpam_sched_in()
arm64/mpam: resctrl: Update resources reset process
arm64/mpam: resctrl: Update closid alloc and free process with bitmap
arm64/mpam: resctrl: Move ctrlmon sysfile write/read function to
mpam_ctrlmon.c
arm64/mpam: Support cdp on allocating monitors
arm64/mpam: resctrl: Support cdp on monitoring data
arm64/mpam: Clean up header files and rearrange declarations
arm64/mpam: resctrl: Remove ctrlmon sysfile
arm64/mpam: resctrl: Remove unnecessary CONFIG_ARM64
arm64/mpam: Implement intpartid narrowing process
arm64/mpam: Using software-defined id for rdtgroup instead of 32-bit
integer
arm64/mpam: resctrl: collect child mon group's monitor data
arm64/mpam: resctrl: Support cpus' monitoring for mon group
arm64/mpam: resctrl: Support priority and hardlimit(Memory bandwidth)
configuration
arm64/mpam: Store intpri and dspri for mpam device reset
arm64/mpam: Squash default priority from mpam device to class
arm64/mpam: Restore extend ctrls' max width for checking schemata
input
arm64/mpam: Re-plan intpartid narrowing process
arm64/mpam: Add hook-events id for ctrl features
arm64/mpam: Integrate monitor data for Memory Bandwidth if cdp enabled
arm64/mpam: Fix MPAM_ESR intPARTID_range error
arm64/mpam: Separate internal and downstream priority event
arm64/mpam: Remap reqpartid,pmg to rmid and intpartid to closid
arm64/mpam: Add wait queue for monitor alloc and free
arm64/mpam: Add resctrl_ctrl_feature structure to manage ctrl features
arm64/mpam: resctrl: Export resource's properties to info directory
arm64/mpam: Split header files into suitable location
arm64/mpam: resctrl: Add rmid file in resctrl sysfs
arm64/mpam: Filter schema control type with ctrl features
arm64/mpam: Simplify mpamid cdp mapping process
arm64/mpam: Set per-cpu's closid to none zero for cdp
ACPI/MPAM: Use acpi_map_pxm_to_node() to get node id for memory node
arm64/mpam: Supplement additional useful ctrl features for mount
options
arm64/mpam: resctrl: Add proper error handling to resctrl_mount()
arm64/mpam: resctrl: Use resctrl_group_init_alloc() for default group
arm64/mpam: resctrl: Allow setting register MPAMCFG_MBW_MIN to 0
arm64/mpam: resctrl: Refresh cpu mask for handling cpuhp
arm64/mpam: Sort domains when cpu online
arm64/mpam: Fix compile warning
arch/arm64/include/asm/mpam.h | 324 +---
arch/arm64/include/asm/mpam_resource.h | 129 --
arch/arm64/include/asm/mpam_sched.h | 8 -
arch/arm64/include/asm/resctrl.h | 514 +++++-
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/mpam.c | 1499 ----------------
arch/arm64/kernel/mpam/Makefile | 3 +
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 961 ++++++++++
arch/arm64/kernel/mpam/mpam_device.c | 1706 ++++++++++++++++++
arch/arm64/kernel/mpam/mpam_device.h | 140 ++
arch/arm64/kernel/mpam/mpam_internal.h | 345 ++++
arch/arm64/kernel/mpam/mpam_mon.c | 334 ++++
arch/arm64/kernel/mpam/mpam_resctrl.c | 2240 ++++++++++++++++++++++++
arch/arm64/kernel/mpam/mpam_resource.h | 228 +++
arch/arm64/kernel/mpam/mpam_setup.c | 608 +++++++
arch/arm64/kernel/mpam_ctrlmon.c | 623 -------
arch/arm64/kernel/mpam_mon.c | 124 --
drivers/acpi/arm64/mpam.c | 87 +-
drivers/base/cacheinfo.c | 38 +
fs/resctrlfs.c | 396 +++--
include/linux/arm_mpam.h | 118 ++
include/linux/cacheinfo.h | 36 +
include/linux/resctrlfs.h | 30 -
23 files changed, 7521 insertions(+), 2972 deletions(-)
delete mode 100644 arch/arm64/include/asm/mpam_resource.h
delete mode 100644 arch/arm64/kernel/mpam.c
create mode 100644 arch/arm64/kernel/mpam/Makefile
create mode 100644 arch/arm64/kernel/mpam/mpam_ctrlmon.c
create mode 100644 arch/arm64/kernel/mpam/mpam_device.c
create mode 100644 arch/arm64/kernel/mpam/mpam_device.h
create mode 100644 arch/arm64/kernel/mpam/mpam_internal.h
create mode 100644 arch/arm64/kernel/mpam/mpam_mon.c
create mode 100644 arch/arm64/kernel/mpam/mpam_resctrl.c
create mode 100644 arch/arm64/kernel/mpam/mpam_resource.h
create mode 100644 arch/arm64/kernel/mpam/mpam_setup.c
delete mode 100644 arch/arm64/kernel/mpam_ctrlmon.c
delete mode 100644 arch/arm64/kernel/mpam_mon.c
create mode 100644 include/linux/arm_mpam.h
--
2.25.1
1
65
23 Feb '21
From: Li ZhiGang <lizhigang(a)kylinos.cn>
Nationz Tech TCM are used for trusted computing, the chip attached via SPI or LPC.
We have a brief verify/test with this driver on KunPeng920 + openEuler system, with externally compiled module.
Signed-off-by: Li ZhiGang <lizhigang(a)kylinos.cn>
---
drivers/staging/Kconfig | 2 +
drivers/staging/Makefile | 2 +
drivers/staging/gmjstcm/Kconfig | 21 +
drivers/staging/gmjstcm/Makefile | 5 +
drivers/staging/gmjstcm/tcm.c | 949 ++++++++++++++++++++++++++
drivers/staging/gmjstcm/tcm.h | 123 ++++
drivers/staging/gmjstcm/tcm_tis_spi.c | 868 +++++++++++++++++++++++
7 files changed, 1970 insertions(+)
create mode 100644 drivers/staging/gmjstcm/Kconfig
create mode 100644 drivers/staging/gmjstcm/Makefile
create mode 100644 drivers/staging/gmjstcm/tcm.c
create mode 100644 drivers/staging/gmjstcm/tcm.h
create mode 100644 drivers/staging/gmjstcm/tcm_tis_spi.c
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 1abf76be2aa8..d51fa4f4e7ca 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -126,4 +126,6 @@ source "drivers/staging/axis-fifo/Kconfig"
source "drivers/staging/erofs/Kconfig"
+source "drivers/staging/gmjstcm/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ab0cbe8815b1..6d41915dad5b 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -53,3 +53,5 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/
obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_EROFS_FS) += erofs/
+obj-$(CONFIG_GMJS_TCM) += gmjstcm/
+
diff --git a/drivers/staging/gmjstcm/Kconfig b/drivers/staging/gmjstcm/Kconfig
new file mode 100644
index 000000000000..5b5397ae1832
--- /dev/null
+++ b/drivers/staging/gmjstcm/Kconfig
@@ -0,0 +1,21 @@
+menu "GMJS TCM support"
+
+config GMJS_TCM
+ bool
+
+config GMJS_TCM_CORE
+ tristate "GMJS TCM core support"
+ depends on ARM64 || MIPS
+ default m
+ select GMJS_TCM
+ help
+ GMJS TCM core support.
+
+config GMJS_TCM_SPI
+ tristate "GMJS TCM support on SPI interface"
+ depends on GMJS_TCM_CORE && SPI_MASTER
+ default m
+ help
+ GMJS TCM support on SPI interface.
+
+endmenu
diff --git a/drivers/staging/gmjstcm/Makefile b/drivers/staging/gmjstcm/Makefile
new file mode 100644
index 000000000000..601c78e44793
--- /dev/null
+++ b/drivers/staging/gmjstcm/Makefile
@@ -0,0 +1,5 @@
+
+obj-$(CONFIG_GMJS_TCM_CORE) += tcm_core.o
+tcm_core-objs := tcm.o
+obj-$(CONFIG_GMJS_TCM_SPI) += tcm_tis_spi.o
+
diff --git a/drivers/staging/gmjstcm/tcm.c b/drivers/staging/gmjstcm/tcm.c
new file mode 100644
index 000000000000..5c41bfa8b423
--- /dev/null
+++ b/drivers/staging/gmjstcm/tcm.c
@@ -0,0 +1,949 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2009 Nationz Technologies Inc.
+ *
+ * Description: Exprot symbol for tcm_tis module
+ *
+ * Major Function: public write read register function etc.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include "tcm.h"
+
+/*
+ * const var
+ */
+enum tcm_const {
+ TCM_MINOR = 224, /* officially assigned */
+ TCM_BUFSIZE = 2048, /* Buffer Size */
+ TCM_NUM_DEVICES = 256, /* Max supporting tcm device number */
+};
+
+/*
+ * CMD duration
+ */
+enum tcm_duration {
+ TCM_SHORT = 0,
+ TCM_MEDIUM = 1,
+ TCM_LONG = 2,
+ TCM_UNDEFINED,
+};
+
+/* Max Total of Command Number */
+#define TCM_MAX_ORDINAL 88 /*243*/
+
+static LIST_HEAD(tcm_chip_list);
+static DEFINE_SPINLOCK(driver_lock); /* spin lock */
+static DECLARE_BITMAP(dev_mask, TCM_NUM_DEVICES);
+
+typedef struct tagTCM_Command {
+ u8 ordinal;
+ u8 DURATION;
+} TCM_Command;
+
+static const TCM_Command TCM_Command_List[TCM_MAX_ORDINAL + 1] = {
+ {/*TCM_ORD_ActivateIdentity, */122, 1},
+ {/*TCM_ORD_CertifyKey, */50, 1},
+ {/*TCM_ORD_CertifyKeyM, */51, 1},
+ {/*TCM_ORD_ChangeAuth, */12, 1},
+ {/*TCM_ORD_ChangeAuthOwner, */16, 0},
+ {/*TCM_ORD_ContinueSelfTeSt, */83, 2},
+ {/*TCM_ORD_CreateCounter, */220, 0},
+ {/*TCM_ORD_CreateWrapKey, */31, 2},
+ {/*TCM_ORD_DiSableForceClear, */94, 0},
+ {/*TCM_ORD_DiSableOwnerClear, */92, 0},
+ {/*TCM_ORD_EStabliShTranSport, */230, 0},
+ {/*TCM_ORD_ExecuteTranSport, */231, 2},
+ {/*TCM_ORD_Extend, */20, 0},
+ {/*TCM_ORD_FieldUpgrade, */170, 2},
+ {/*TCM_ORD_FluShSpecific, */186, 0},
+ {/*TCM_ORD_ForceClear, */93, 0},
+ {/*TCM_ORD_GetAuditDigeSt, */133, 0},
+ {/*TCM_ORD_GetAuditDigeStSigned, */134, 1},
+ {/*TCM_ORD_GetCapability, */101, 0},
+ {/*TCM_ORD_GetPubKey, */33, 0},
+ {/*TCM_ORD_GetRandoM, */70, 0},
+ {/*TCM_ORD_GetTeStReSult, */84, 0},
+ {/*TCM_ORD_GetTickS, */241, 0},
+ {/*TCM_ORD_IncreMentCounter, */221, 0},
+ {/*TCM_ORD_LoadContext, */185, 1},
+ {/*TCM_ORD_MakeIdentity, */121, 2},
+ {/*TCM_ORD_NV_DefineSpace, */204, 0},
+ {/*TCM_ORD_NV_ReadValue, */207, 0},
+ {/*TCM_ORD_NV_ReadValueAuth, */208, 0},
+ {/*TCM_ORD_NV_WriteValue, */205, 0},
+ {/*TCM_ORD_NV_WriteValueAuth, */206, 0},
+ {/*TCM_ORD_OwnerClear, */91, 0},
+ {/*TCM_ORD_OwnerReadInternalPub, */129, 0},
+ {/*TCM_ORD_OwnerSetDiSable, */110, 0},
+ {/*TCM_ORD_PCR_ReSet, */200, 0},
+ {/*TCM_ORD_PcrRead, */21, 0},
+ {/*TCM_ORD_PhySicalDiSable, */112, 0},
+ {/*TCM_ORD_PhySicalEnable, */111, 0},
+ {/*TCM_ORD_PhySicalSetDeactivated, */114, 0},
+ {/*TCM_ORD_Quote, */22, 1},
+ {/*TCM_ORD_QuoteM, */62, 1},
+ {/*TCM_ORD_ReadCounter, */222, 0},
+ {/*TCM_ORD_ReadPubek, */124, 0},
+ {/*TCM_ORD_ReleaSeCounter, */223, 0},
+ {/*TCM_ORD_ReleaSeCounterOwner, */224, 0},
+ {/*TCM_ORD_ReleaSeTranSportSigned, */232, 1},
+ {/*TCM_ORD_ReSetLockValue, */64, 0},
+ {/*TCM_ORD_RevokeTruSt, */128, 0},
+ {/*TCM_ORD_SaveContext, */184, 1},
+ {/*TCM_ORD_SaveState, */152, 1},
+ {/*TCM_ORD_Seal, */23, 1},
+ {/*TCM_ORD_Sealx, */61, 1},
+ {/*TCM_ORD_SelfTeStFull, */80, 2},
+ {/*TCM_ORD_SetCapability, */63, 0},
+ {/*TCM_ORD_SetOperatorAuth, */116, 0},
+ {/*TCM_ORD_SetOrdinalAuditStatuS, */141, 0},
+ {/*TCM_ORD_SetOwnerInStall, */113, 0},
+ {/*TCM_ORD_SetTeMpDeactivated, */115, 0},
+ {/*TCM_ORD_Sign, */60, 1},
+ {/*TCM_ORD_Startup, */153, 0},
+ {/*TCM_ORD_TakeOwnerShip, */13, 1},
+ {/*TCM_ORD_TickStaMpBlob, */242, 1},
+ {/*TCM_ORD_UnSeal, */24, 1},
+ {/*TSC_ORD_PhySicalPreSence, */10, 0},
+ {/*TSC_ORD_ReSetEStabliShMentBit, */11, 0},
+ {/*TCM_ORD_WrapKey, */189, 2},
+ {/*TCM_ORD_APcreate, */191, 0},
+ {/*TCM_ORD_APTerMinate, */192, 0},
+ {/*TCM_ORD_CreateMigratedBlob, */193, 1},
+ {/*TCM_ORD_ConvertMigratedBlob, */194, 1},
+ {/*TCM_ORD_AuthorizeMigrationKey, */195, 0},
+ {/*TCM_ORD_SMS4Encrypt, */197, 1},
+ {/*TCM_ORD_SMS4Decrypt, */198, 1},
+ {/*TCM_ORD_ReadEKCert, */199, 1},
+ {/*TCM_ORD_WriteEKCert, */233, 1},
+ {/*TCM_ORD_SCHStart, */234, 0},
+ {/*TCM_ORD_SCHUpdata, */235, 0},
+ {/*TCM_ORD_SCHCoMplete, */236, 0},
+ {/*TCM_ORD_SCHCoMpleteExtend, */237, 0},
+ {/*TCM_ORD_ECCDecrypt, */238, 1},
+ {/*TCM_ORD_LoadKey, */239, 1},
+ {/*TCM_ORD_CreateEndorSeMentKeyPair, */120, 2},
+ {/*TCM_ORD_CreateRevocableEK, */127, 2},
+ {/*TCM_ORD_ReleaSeECCExchangeSeSSion, */174, 1},
+ {/*TCM_ORD_CreateECCExchangeSeSSion, */175, 1},
+ {/*TCM_ORD_GetKeyECCExchangeSeSSion, */176, 1},
+ {/*TCM_ORD_ActivatePEK, */217, 1},
+ {/*TCM_ORD_ActivatePEKCert, */218, 1},
+ {0, 0}
+};
+
+static void user_reader_timeout(struct timer_list *t)
+{
+ struct tcm_chip *chip = from_timer(chip, t, user_read_timer);
+
+ schedule_work(&chip->work);
+}
+
+static void timeout_work(struct work_struct *work)
+{
+ struct tcm_chip *chip = container_of(work, struct tcm_chip, work);
+
+ mutex_lock(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TCM_BUFSIZE);
+ mutex_unlock(&chip->buffer_mutex);
+}
+
+unsigned long tcm_calc_ordinal_duration(struct tcm_chip *chip,
+ u32 ordinal)
+{
+ int duration_idx = TCM_UNDEFINED;
+ int duration = 0;
+ int i = 0;
+
+ for (i = 0; i < TCM_MAX_ORDINAL; i++) {
+ if (ordinal == TCM_Command_List[i].ordinal) {
+ duration_idx = TCM_Command_List[i].DURATION;
+ break;
+ }
+ }
+
+ if (duration_idx != TCM_UNDEFINED)
+ duration = chip->vendor.duration[duration_idx];
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tcm_calc_ordinal_duration);
+
+/*
+ * Internal kernel interface to transmit TCM commands
+ * buff format: TAG(2 bytes) + Total Size(4 bytes ) +
+ * Command Ordinal(4 bytes ) + ......
+ */
+static ssize_t tcm_transmit(struct tcm_chip *chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t rc = 0;
+ u32 count = 0, ordinal = 0;
+ unsigned long stop = 0;
+
+ count = be32_to_cpu(*((__be32 *)(buf + 2))); /* buff size */
+ ordinal = be32_to_cpu(*((__be32 *)(buf + 6))); /* command ordinal */
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) { /* buff size err ,invalid buff stream */
+ dev_err(chip->dev, "invalid count value %x, %zx\n",
+ count, bufsiz);
+ return -E2BIG;
+ }
+
+ mutex_lock(&chip->tcm_mutex); /* enter mutex */
+
+ rc = chip->vendor.send(chip, (u8 *)buf, count);
+ if (rc < 0) {
+ dev_err(chip->dev, "%s: tcm_send: error %zd\n",
+ __func__, rc);
+ goto out;
+ }
+
+ if (chip->vendor.irq)
+ goto out_recv;
+
+ stop = jiffies + tcm_calc_ordinal_duration(chip,
+ ordinal); /* cmd duration */
+ do {
+ u8 status = chip->vendor.status(chip);
+
+ if ((status & chip->vendor.req_complete_mask) ==
+ chip->vendor.req_complete_val)
+ goto out_recv;
+
+ if ((status == chip->vendor.req_canceled)) {
+ dev_err(chip->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TCM_TIMEOUT); /* CHECK */
+ rmb();
+ } while (time_before(jiffies, stop));
+ /* time out */
+ chip->vendor.cancel(chip);
+ dev_err(chip->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
+
+out_recv:
+ rc = chip->vendor.recv(chip, (u8 *)buf, bufsiz);
+ if (rc < 0)
+ dev_err(chip->dev, "%s: tcm_recv: error %zd\n",
+ __func__, rc);
+out:
+ mutex_unlock(&chip->tcm_mutex);
+ return rc;
+}
+
+#define TCM_DIGEST_SIZE 32
+#define TCM_ERROR_SIZE 10
+#define TCM_RET_CODE_IDX 6
+#define TCM_GET_CAP_RET_SIZE_IDX 10
+#define TCM_GET_CAP_RET_UINT32_1_IDX 14
+#define TCM_GET_CAP_RET_UINT32_2_IDX 18
+#define TCM_GET_CAP_RET_UINT32_3_IDX 22
+#define TCM_GET_CAP_RET_UINT32_4_IDX 26
+#define TCM_GET_CAP_PERM_DISABLE_IDX 16
+#define TCM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TCM_GET_CAP_RET_BOOL_1_IDX 14
+#define TCM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TCM_CAP_IDX 13
+#define TCM_CAP_SUBCAP_IDX 21
+
+enum tcm_capabilities {
+ TCM_CAP_FLAG = 4,
+ TCM_CAP_PROP = 5,
+};
+
+enum tcm_sub_capabilities {
+ TCM_CAP_PROP_PCR = 0x1, /* tcm 0x101 */
+ TCM_CAP_PROP_MANUFACTURER = 0x3, /* tcm 0x103 */
+ TCM_CAP_FLAG_PERM = 0x8, /* tcm 0x108 */
+ TCM_CAP_FLAG_VOL = 0x9, /* tcm 0x109 */
+ TCM_CAP_PROP_OWNER = 0x11, /* tcm 0x101 */
+ TCM_CAP_PROP_TIS_TIMEOUT = 0x15, /* tcm 0x115 */
+ TCM_CAP_PROP_TIS_DURATION = 0x20, /* tcm 0x120 */
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TCM_CAP_PROP or TCM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tcm_cap[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND 0xc1*/
+ 0, 0, 0, 22, /* length */
+ 0, 0, 128, 101, /* TCM_ORD_GetCapability */
+ 0, 0, 0, 0, /* TCM_CAP_<TYPE> */
+ 0, 0, 0, 4, /* TCM_CAP_SUB_<TYPE> size */
+ 0, 0, 1, 0 /* TCM_CAP_SUB_<TYPE> */
+};
+
+static ssize_t transmit_cmd(struct tcm_chip *chip, u8 *data, int len,
+ char *desc)
+{
+ int err = 0;
+
+ len = tcm_transmit(chip, data, len);
+ if (len < 0)
+ return len;
+ if (len == TCM_ERROR_SIZE) {
+ err = be32_to_cpu(*((__be32 *)(data + TCM_RET_CODE_IDX)));
+ dev_dbg(chip->dev, "A TCM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Get default timeouts value form tcm by GetCapability with TCM_CAP_PROP_TIS_TIMEOUT prop
+ */
+void tcm_get_timeouts(struct tcm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tcm_cap), 30)];
+ ssize_t rc = 0;
+ u32 timeout = 0;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+ if (rc)
+ goto duration;
+
+ if (be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_SIZE_IDX))) !=
+ 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_TIS_DURATION;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the durations");
+ if (rc)
+ return;
+
+ if (be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_SIZE_IDX))) !=
+ 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TCM_SHORT] =
+ msecs_to_jiffies(be32_to_cpu(*((__be32 *)(data +
+ TCM_GET_CAP_RET_UINT32_1_IDX))));
+ chip->vendor.duration[TCM_MEDIUM] =
+ msecs_to_jiffies(be32_to_cpu(*((__be32 *)(data +
+ TCM_GET_CAP_RET_UINT32_2_IDX))));
+ chip->vendor.duration[TCM_LONG] =
+ msecs_to_jiffies(be32_to_cpu(*((__be32 *)(data +
+ TCM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tcm_get_timeouts);
+
+ssize_t tcm_show_enabled(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tcm_cap), 35)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_FLAG;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_PERM_DISABLE_IDX])
+ return sprintf(buf, "disable\n");
+ else
+ return sprintf(buf, "enable\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_enabled);
+
+ssize_t tcm_show_active(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tcm_cap), 35)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_FLAG;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_PERM_INACTIVE_IDX])
+ return sprintf(buf, "deactivated\n");
+ else
+ return sprintf(buf, "activated\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_active);
+
+ssize_t tcm_show_owned(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[sizeof(tcm_cap)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_OWNER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the owner state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_RET_BOOL_1_IDX])
+ return sprintf(buf, "Owner installed\n");
+ else
+ return sprintf(buf, "Owner have not installed\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_owned);
+
+ssize_t tcm_show_temp_deactivated(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[sizeof(tcm_cap)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_FLAG;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_FLAG_VOL;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the temporary state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_TEMP_INACTIVE_IDX])
+ return sprintf(buf, "Temp deactivated\n");
+ else
+ return sprintf(buf, "activated\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_temp_deactivated);
+
+static const u8 pcrread[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 128, 21, /* TCM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+ssize_t tcm_show_pcrs(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[1024];
+ ssize_t rc = 0;
+ int i = 0, j = 0, num_pcrs = 0;
+ __be32 index = 0;
+ char *str = buf;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_PCR;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the number of PCRS");
+ if (rc)
+ return 0;
+
+ num_pcrs = be32_to_cpu(*((__be32 *)(data + 14)));
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read a PCR");
+ if (rc)
+ goto out;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TCM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ memset(data, 0, 1024);
+ }
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tcm_show_pcrs);
+
+#define READ_PUBEK_RESULT_SIZE 128
+static const u8 readpubek[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 42, /* length */
+ 0, 0, 128, 124, /* TCM_ORD_ReadPubek */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* NONCE */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+ssize_t tcm_show_pubek(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE] = {0};
+ ssize_t err = 0;
+ int i = 0, rc = 0;
+ char *str = buf;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+
+ err = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read the PUBEK");
+ if (err)
+ goto out;
+
+ str += sprintf(str, "PUBEK:");
+ for (i = 0 ; i < 65 ; i++) {
+ if ((i) % 16 == 0)
+ str += sprintf(str, "\n");
+ str += sprintf(str, "%02X ", data[i+10]);
+ }
+
+ str += sprintf(str, "\n");
+out:
+ rc = str - buf;
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tcm_show_pubek);
+
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
+static const u8 cap_version[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 128, 101, /* TCM_ORD_GetCapability */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+ssize_t tcm_show_caps(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[max_t(int, max(ARRAY_SIZE(tcm_cap), ARRAY_SIZE(cap_version)), 30)];
+ ssize_t rc = 0;
+ char *str = buf;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_MANUFACTURER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the 1.1 version");
+ if (rc)
+ goto out;
+
+ str += sprintf(str, "Firmware version: %02X.%02X.%02X.%02X\n",
+ (int)data[14], (int)data[15], (int)data[16],
+ (int)data[17]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tcm_show_caps);
+
+ssize_t tcm_store_cancel(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor.cancel(chip);
+ return count;
+}
+EXPORT_SYMBOL_GPL(tcm_store_cancel);
+
+/*
+ * Device file system interface to the TCM
+ * when App call file open in usr space ,this func will respone
+ */
+int tcm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tcm_chip *chip = NULL, *pos = NULL;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tcm_chip_list, list) {
+ if (pos->vendor.miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(chip->dev, "Another process owns this TCM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ get_device(chip->dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TCM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ put_device(chip->dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tcm_open);
+
+int tcm_release(struct inode *inode, struct file *file)
+{
+ struct tcm_chip *chip = file->private_data;
+
+ spin_lock(&driver_lock);
+ file->private_data = NULL;
+ chip->num_opens--;
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ flush_work(&chip->work);
+ atomic_set(&chip->data_pending, 0);
+ put_device(chip->dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_release);
+
+ssize_t tcm_write(struct file *file, const char __user *buf,
+ size_t size, loff_t *off)
+{
+ struct tcm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /*
+ * cannot perform a write until the read has cleared
+ * either via tcm_read or a user_read_timer timeout
+ */
+ while (atomic_read(&chip->data_pending) != 0)
+ msleep(TCM_TIMEOUT);
+
+ mutex_lock(&chip->buffer_mutex);
+
+ if (in_size > TCM_BUFSIZE)
+ in_size = TCM_BUFSIZE;
+
+ if (copy_from_user(chip->data_buffer, (void __user *)buf, in_size)) {
+ mutex_unlock(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tcm command send and result receive */
+ out_size = tcm_transmit(chip, chip->data_buffer, TCM_BUFSIZE);
+
+ if (out_size >= 0) {
+ atomic_set(&chip->data_pending, out_size);
+ mutex_unlock(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
+ } else
+ mutex_unlock(&chip->buffer_mutex);
+
+ return in_size;
+}
+EXPORT_SYMBOL_GPL(tcm_write);
+
+ssize_t tcm_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
+{
+ struct tcm_chip *chip = file->private_data;
+ int ret_size = 0;
+
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ flush_work(&chip->work);
+ ret_size = atomic_read(&chip->data_pending);
+ atomic_set(&chip->data_pending, 0);
+ if (ret_size > 0) { /* relay data */
+ if (size < ret_size)
+ ret_size = size;
+
+ mutex_lock(&chip->buffer_mutex);
+ if (copy_to_user(buf, chip->data_buffer, ret_size))
+ ret_size = -EFAULT;
+ mutex_unlock(&chip->buffer_mutex);
+ }
+
+ return ret_size;
+}
+EXPORT_SYMBOL_GPL(tcm_read);
+
+void tcm_remove_hardware(struct device *dev)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL) {
+ dev_err(dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+ list_del(&chip->list);
+ spin_unlock(&driver_lock);
+
+ dev_set_drvdata(dev, NULL);
+ misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
+
+ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
+ /* tcm_bios_log_teardown(chip->bios_dir); */
+
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip);
+ put_device(dev);
+}
+EXPORT_SYMBOL_GPL(tcm_remove_hardware);
+
+static u8 savestate[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 128, 152 /* TCM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TCM state
+ * so that it can be restored.
+ */
+int tcm_pm_suspend(struct device *dev, pm_message_t pm_state)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ tcm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_pm_suspend);
+
+int tcm_pm_suspend_p(struct device *dev)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ tcm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_pm_suspend_p);
+
+void tcm_startup(struct tcm_chip *chip)
+{
+ u8 start_up[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 12, /* blob length (in bytes) */
+ 0, 0, 128, 153, /* TCM_ORD_SaveState */
+ 0, 1
+ };
+ if (chip == NULL)
+ return;
+ tcm_transmit(chip, start_up, sizeof(start_up));
+}
+EXPORT_SYMBOL_GPL(tcm_startup);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TCM state.
+ */
+int tcm_pm_resume(struct device *dev)
+{
+ u8 start_up[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 12, /* blob length (in bytes) */
+ 0, 0, 128, 153, /* TCM_ORD_SaveState */
+ 0, 1
+ };
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+ /* dev_info(chip->dev ,"--call tcm_pm_resume\n"); */
+ if (chip == NULL)
+ return -ENODEV;
+
+ tcm_transmit(chip, start_up, sizeof(start_up));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_pm_resume);
+
+/*
+ * Called from tcm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+struct tcm_chip *tcm_register_hardware(struct device *dev,
+ const struct tcm_vendor_specific *entry)
+{
+ int rc;
+#define DEVNAME_SIZE 7
+
+ char *devname = NULL;
+ struct tcm_chip *chip = NULL;
+
+ /* Driver specific per-device data */
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ dev_err(dev, "chip kzalloc err\n");
+ return NULL;
+ }
+
+ mutex_init(&chip->buffer_mutex);
+ mutex_init(&chip->tcm_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ INIT_WORK(&chip->work, timeout_work);
+ timer_setup(&chip->user_read_timer, user_reader_timeout, 0);
+
+ memcpy(&chip->vendor, entry, sizeof(struct tcm_vendor_specific));
+
+ chip->dev_num = find_first_zero_bit(dev_mask, TCM_NUM_DEVICES);
+
+ if (chip->dev_num >= TCM_NUM_DEVICES) {
+ dev_err(dev, "No available tcm device numbers\n");
+ kfree(chip);
+ return NULL;
+ } else if (chip->dev_num == 0)
+ chip->vendor.miscdev.minor = TCM_MINOR;
+ else
+ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ set_bit(chip->dev_num, dev_mask);
+
+ devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+ scnprintf(devname, DEVNAME_SIZE, "%s%d", "tcm", chip->dev_num);
+ chip->vendor.miscdev.name = devname;
+
+ /* chip->vendor.miscdev.dev = dev; */
+
+ chip->dev = get_device(dev);
+
+ if (misc_register(&chip->vendor.miscdev)) {
+ dev_err(chip->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor.miscdev.name,
+ chip->vendor.miscdev.minor);
+ put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip);
+ kfree(devname);
+ return NULL;
+ }
+
+ spin_lock(&driver_lock);
+ dev_set_drvdata(dev, chip);
+ list_add(&chip->list, &tcm_chip_list);
+ spin_unlock(&driver_lock);
+
+ rc = sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
+ /* chip->bios_dir = tcm_bios_log_setup(devname); */
+
+ return chip;
+}
+EXPORT_SYMBOL_GPL(tcm_register_hardware);
+
+static int __init tcm_init_module(void)
+{
+ return 0;
+}
+
+static void __exit tcm_exit_module(void)
+{
+}
+
+module_init(tcm_init_module);
+module_exit(tcm_exit_module);
+
+MODULE_AUTHOR("Nationz Technologies Inc.");
+MODULE_DESCRIPTION("TCM Driver");
+MODULE_VERSION("1.1.1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gmjstcm/tcm.h b/drivers/staging/gmjstcm/tcm.h
new file mode 100644
index 000000000000..b8cafe78d590
--- /dev/null
+++ b/drivers/staging/gmjstcm/tcm.h
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2009 Nationz Technologies Inc.
+ *
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+struct device;
+struct tcm_chip;
+
+enum tcm_timeout {
+ TCM_TIMEOUT = 5,
+};
+
+/* TCM addresses */
+enum tcm_addr {
+ TCM_SUPERIO_ADDR = 0x2E,
+ TCM_ADDR = 0x4E,
+};
+
+extern ssize_t tcm_show_pubek(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_pcrs(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_caps(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_store_cancel(struct device *, struct device_attribute *attr,
+ const char *, size_t);
+extern ssize_t tcm_show_enabled(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_active(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_owned(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_temp_deactivated(struct device *,
+ struct device_attribute *attr, char *);
+
+struct tcm_vendor_specific {
+ const u8 req_complete_mask;
+ const u8 req_complete_val;
+ const u8 req_canceled;
+ void __iomem *iobase; /* ioremapped address */
+ void __iomem *iolbc;
+ unsigned long base; /* TCM base address */
+
+ int irq;
+
+ int region_size;
+ int have_region;
+
+ int (*recv)(struct tcm_chip *, u8 *, size_t);
+ int (*send)(struct tcm_chip *, u8 *, size_t);
+ void (*cancel)(struct tcm_chip *);
+ u8 (*status)(struct tcm_chip *);
+ struct miscdevice miscdev;
+ struct attribute_group *attr_group;
+ struct list_head list;
+ int locality;
+ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+ unsigned long duration[3]; /* jiffies */
+
+ wait_queue_head_t read_queue;
+ wait_queue_head_t int_queue;
+};
+
+struct tcm_chip {
+ struct device *dev; /* Device stuff */
+
+ int dev_num; /* /dev/tcm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tcm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ struct mutex buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct work_struct work;
+ struct mutex tcm_mutex; /* tcm is processing */
+
+ struct tcm_vendor_specific vendor;
+
+ struct dentry **bios_dir;
+
+ struct list_head list;
+};
+
+#define to_tcm_chip(n) container_of(n, struct tcm_chip, vendor)
+
+static inline int tcm_read_index(int base, int index)
+{
+ outb(index, base);
+ return inb(base+1) & 0xFF;
+}
+
+static inline void tcm_write_index(int base, int index, int value)
+{
+ outb(index, base);
+ outb(value & 0xFF, base+1);
+}
+extern void tcm_startup(struct tcm_chip *);
+extern void tcm_get_timeouts(struct tcm_chip *);
+extern unsigned long tcm_calc_ordinal_duration(struct tcm_chip *, u32);
+extern struct tcm_chip *tcm_register_hardware(struct device *,
+ const struct tcm_vendor_specific *);
+extern int tcm_open(struct inode *, struct file *);
+extern int tcm_release(struct inode *, struct file *);
+extern ssize_t tcm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tcm_read(struct file *, char __user *, size_t, loff_t *);
+extern void tcm_remove_hardware(struct device *);
+extern int tcm_pm_suspend(struct device *, pm_message_t);
+extern int tcm_pm_suspend_p(struct device *);
+extern int tcm_pm_resume(struct device *);
+
diff --git a/drivers/staging/gmjstcm/tcm_tis_spi.c b/drivers/staging/gmjstcm/tcm_tis_spi.c
new file mode 100644
index 000000000000..db30a5b4c47d
--- /dev/null
+++ b/drivers/staging/gmjstcm/tcm_tis_spi.c
@@ -0,0 +1,868 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Kylin Tech. Co., Ltd.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/acpi.h>
+#include <linux/spi/spi.h>
+
+#include "tcm.h"
+
+#if !defined(CONFIG_KYLINOS_SERVER) && !defined(CONFIG_KYLINOS_DESKTOP)
+static int is_ft_all(void) {
+ return 0;
+}
+#endif
+
+#define TCM_HEADER_SIZE 10
+
+static bool tcm_debug;
+module_param_named(debug, tcm_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn TCM debugging mode on and off");
+
+#define tcm_dbg(fmt, args...) \
+{ \
+ if (tcm_debug) \
+ pr_err(fmt, ## args); \
+}
+
+enum tis_access {
+ TCM_ACCESS_VALID = 0x80,
+ TCM_ACCESS_ACTIVE_LOCALITY = 0x20,
+ TCM_ACCESS_REQUEST_PENDING = 0x04,
+ TCM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+ TCM_STS_VALID = 0x80,
+ TCM_STS_COMMAND_READY = 0x40,
+ TCM_STS_GO = 0x20,
+ TCM_STS_DATA_AVAIL = 0x10,
+ TCM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+ TCM_GLOBAL_INT_ENABLE = 0x80000000,
+ TCM_INTF_BURST_COUNT_STATIC = 0x100,
+ TCM_INTF_CMD_READY_INT = 0x080,
+ TCM_INTF_INT_EDGE_FALLING = 0x040,
+ TCM_INTF_INT_EDGE_RISING = 0x020,
+ TCM_INTF_INT_LEVEL_LOW = 0x010,
+ TCM_INTF_INT_LEVEL_HIGH = 0x008,
+ TCM_INTF_LOCALITY_CHANGE_INT = 0x004,
+ TCM_INTF_STS_VALID_INT = 0x002,
+ TCM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+ TIS_SHORT_TIMEOUT = 750, /* ms */
+ TIS_LONG_TIMEOUT = 2000, /* 2 sec */
+};
+
+#define TCM_ACCESS(l) (0x0000 | ((l) << 12))
+#define TCM_INT_ENABLE(l) (0x0008 | ((l) << 12)) /* interperet */
+#define TCM_INT_VECTOR(l) (0x000C | ((l) << 12))
+#define TCM_INT_STATUS(l) (0x0010 | ((l) << 12))
+#define TCM_INTF_CAPS(l) (0x0014 | ((l) << 12))
+#define TCM_STS(l) (0x0018 | ((l) << 12))
+#define TCM_DATA_FIFO(l) (0x0024 | ((l) << 12))
+
+#define TCM_DID_VID(l) (0x0F00 | ((l) << 12))
+#define TCM_RID(l) (0x0F04 | ((l) << 12))
+
+#define TIS_MEM_BASE_huawei 0x3fed40000LL
+
+#define MAX_SPI_FRAMESIZE 64
+
+//
+#define _CPU_FT2000A4
+#define REUSE_CONF_REG_BASE 0x28180208
+#define REUSE_GPIO1_A5_BASE 0x28005000
+
+static void *__iomem reuse_conf_reg;
+static void *__iomem gpio1_a5;
+
+//
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+struct chip_data {
+ u8 cs;
+ u8 tmode;
+ u8 type;
+ u8 poll_mode;
+ u16 clk_div;
+ u32 speed_hz;
+ void (*cs_control)(u32 command);
+};
+
+struct tcm_tis_spi_phy {
+ struct spi_device *spi_device;
+ struct completion ready;
+ u8 *iobuf;
+};
+
+int tcm_tis_spi_transfer(struct device *dev, u32 addr, u16 len,
+ u8 *in, const u8 *out)
+{
+ struct tcm_tis_spi_phy *phy = dev_get_drvdata(dev);
+ int ret = 0;
+ struct spi_message m;
+ struct spi_transfer spi_xfer;
+ u8 transfer_len;
+
+ tcm_dbg("TCM-dbg: %s, addr: 0x%x, len: %x, %s\n",
+ __func__, addr, len, (in) ? "in" : "out");
+
+ spi_bus_lock(phy->spi_device->master);
+
+ /* set gpio1_a5 to LOW */
+ if (is_ft_all() && (phy->spi_device->chip_select == 0)) {
+ iowrite32(0x0, gpio1_a5);
+ }
+
+ while (len) {
+ transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+
+ phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+ phy->iobuf[1] = 0xd4;
+ phy->iobuf[2] = addr >> 8;
+ phy->iobuf[3] = addr;
+
+ memset(&spi_xfer, 0, sizeof(spi_xfer));
+ spi_xfer.tx_buf = phy->iobuf;
+ spi_xfer.rx_buf = phy->iobuf;
+ spi_xfer.len = 4;
+ spi_xfer.cs_change = 1;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+ ret = spi_sync_locked(phy->spi_device, &m);
+ if (ret < 0)
+ goto exit;
+
+ spi_xfer.cs_change = 0;
+ spi_xfer.len = transfer_len;
+ spi_xfer.delay_usecs = 5;
+
+ if (in) {
+ spi_xfer.tx_buf = NULL;
+ } else if (out) {
+ spi_xfer.rx_buf = NULL;
+ memcpy(phy->iobuf, out, transfer_len);
+ out += transfer_len;
+ }
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+ reinit_completion(&phy->ready);
+ ret = spi_sync_locked(phy->spi_device, &m);
+ if (ret < 0)
+ goto exit;
+
+ if (in) {
+ memcpy(in, phy->iobuf, transfer_len);
+ in += transfer_len;
+ }
+
+ len -= transfer_len;
+ }
+
+exit:
+ /* set gpio1_a5 to HIGH */
+ if (is_ft_all() && (phy->spi_device->chip_select == 0)) {
+ iowrite32(0x20, gpio1_a5);
+ }
+
+ spi_bus_unlock(phy->spi_device->master);
+ tcm_dbg("TCM-dbg: ret: %d\n", ret);
+ return ret;
+}
+
+static int tcm_tis_read8(struct device *dev,
+ u32 addr, u16 len, u8 *result)
+{
+ return tcm_tis_spi_transfer(dev, addr, len, result, NULL);
+}
+
+static int tcm_tis_write8(struct device *dev,
+ u32 addr, u16 len, u8 *value)
+{
+ return tcm_tis_spi_transfer(dev, addr, len, NULL, value);
+}
+
+static int tcm_tis_readb(struct device *dev, u32 addr, u8 *value)
+{
+ return tcm_tis_read8(dev, addr, sizeof(u8), value);
+}
+
+static int tcm_tis_writeb(struct device *dev, u32 addr, u8 value)
+{
+ return tcm_tis_write8(dev, addr, sizeof(u8), &value);
+}
+
+static int tcm_tis_readl(struct device *dev, u32 addr, u32 *result)
+{
+ int rc;
+ __le32 result_le;
+
+ rc = tcm_tis_read8(dev, addr, sizeof(u32), (u8 *)&result_le);
+ tcm_dbg("TCM-dbg: result_le: 0x%x\n", result_le);
+ if (!rc)
+ *result = le32_to_cpu(result_le);
+
+ return rc;
+}
+
+static int tcm_tis_writel(struct device *dev, u32 addr, u32 value)
+{
+ int rc;
+ __le32 value_le;
+
+ value_le = cpu_to_le32(value);
+ rc = tcm_tis_write8(dev, addr, sizeof(u32), (u8 *)&value_le);
+
+ return rc;
+}
+
+static int request_locality(struct tcm_chip *chip, int l);
+static void release_locality(struct tcm_chip *chip, int l, int force);
+static void cleanup_tis(void)
+{
+ int ret;
+ u32 inten;
+ struct tcm_vendor_specific *i, *j;
+ struct tcm_chip *chip;
+
+ spin_lock(&tis_lock);
+ list_for_each_entry_safe(i, j, &tis_chips, list) {
+ chip = to_tcm_chip(i);
+ ret = tcm_tis_readl(chip->dev,
+ TCM_INT_ENABLE(chip->vendor.locality), &inten);
+ if (ret < 0)
+ return;
+
+ tcm_tis_writel(chip->dev, TCM_INT_ENABLE(chip->vendor.locality),
+ ~TCM_GLOBAL_INT_ENABLE & inten);
+ release_locality(chip, chip->vendor.locality, 1);
+ }
+ spin_unlock(&tis_lock);
+}
+
+static void tcm_tis_init(struct tcm_chip *chip)
+{
+ int ret;
+ u8 rid;
+ u32 vendor, intfcaps;
+
+ ret = tcm_tis_readl(chip->dev, TCM_DID_VID(0), &vendor);
+
+ if ((vendor & 0xffff) != 0x19f5 && (vendor & 0xffff) != 0x1B4E)
+ pr_info("there is no Nationz TCM on you computer\n");
+
+ ret = tcm_tis_readb(chip->dev, TCM_RID(0), &rid);
+ if (ret < 0)
+ return;
+ pr_info("kylin: 2019-09-21 1.2 TCM (device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, rid);
+
+ /* Figure out the capabilities */
+ ret = tcm_tis_readl(chip->dev,
+ TCM_INTF_CAPS(chip->vendor.locality), &intfcaps);
+ if (ret < 0)
+ return;
+
+ if (request_locality(chip, 0) != 0)
+ pr_err("tcm request_locality err\n");
+
+ atomic_set(&chip->data_pending, 0);
+}
+
+static void tcm_handle_err(struct tcm_chip *chip)
+{
+ cleanup_tis();
+ tcm_tis_init(chip);
+}
+
+static bool check_locality(struct tcm_chip *chip, int l)
+{
+ int ret;
+ u8 access;
+
+ ret = tcm_tis_readb(chip->dev, TCM_ACCESS(l), &access);
+ tcm_dbg("TCM-dbg: access: 0x%x\n", access);
+ if (ret < 0)
+ return false;
+
+ if ((access & (TCM_ACCESS_ACTIVE_LOCALITY | TCM_ACCESS_VALID)) ==
+ (TCM_ACCESS_ACTIVE_LOCALITY | TCM_ACCESS_VALID)) {
+ chip->vendor.locality = l;
+ return true;
+ }
+
+ return false;
+}
+
+static int request_locality(struct tcm_chip *chip, int l)
+{
+ unsigned long stop;
+
+ if (check_locality(chip, l))
+ return l;
+
+ tcm_tis_writeb(chip->dev, TCM_ACCESS(l), TCM_ACCESS_REQUEST_USE);
+
+ /* wait for burstcount */
+ stop = jiffies + chip->vendor.timeout_a;
+ do {
+ if (check_locality(chip, l))
+ return l;
+ msleep(TCM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+
+ return -1;
+}
+
+static void release_locality(struct tcm_chip *chip, int l, int force)
+{
+ int ret;
+ u8 access;
+
+ ret = tcm_tis_readb(chip->dev, TCM_ACCESS(l), &access);
+ if (ret < 0)
+ return;
+ if (force || (access & (TCM_ACCESS_REQUEST_PENDING | TCM_ACCESS_VALID)) ==
+ (TCM_ACCESS_REQUEST_PENDING | TCM_ACCESS_VALID))
+ tcm_tis_writeb(chip->dev,
+ TCM_ACCESS(l), TCM_ACCESS_ACTIVE_LOCALITY);
+}
+
+static u8 tcm_tis_status(struct tcm_chip *chip)
+{
+ int ret;
+ u8 status;
+
+ ret = tcm_tis_readb(chip->dev,
+ TCM_STS(chip->vendor.locality), &status);
+ tcm_dbg("TCM-dbg: status: 0x%x\n", status);
+ if (ret < 0)
+ return 0;
+
+ return status;
+}
+
+static void tcm_tis_ready(struct tcm_chip *chip)
+{
+ /* this causes the current command to be aboreted */
+ tcm_tis_writeb(chip->dev, TCM_STS(chip->vendor.locality),
+ TCM_STS_COMMAND_READY);
+}
+
+static int get_burstcount(struct tcm_chip *chip)
+{
+ int ret;
+ unsigned long stop;
+ u8 tmp, tmp1;
+ int burstcnt = 0;
+
+ /* wait for burstcount */
+ /* which timeout value, spec has 2 answers (c & d) */
+ stop = jiffies + chip->vendor.timeout_d;
+ do {
+ ret = tcm_tis_readb(chip->dev,
+ TCM_STS(chip->vendor.locality) + 1,
+ &tmp);
+ tcm_dbg("TCM-dbg: burstcnt: 0x%x\n", burstcnt);
+ if (ret < 0)
+ return -EINVAL;
+ ret = tcm_tis_readb(chip->dev,
+ (TCM_STS(chip->vendor.locality) + 2),
+ &tmp1);
+ tcm_dbg("TCM-dbg: burstcnt: 0x%x\n", burstcnt);
+ if (ret < 0)
+ return -EINVAL;
+
+ burstcnt = tmp | (tmp1 << 8);
+ if (burstcnt)
+ return burstcnt;
+ msleep(TCM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+
+ return -EBUSY;
+}
+
+static int wait_for_stat(struct tcm_chip *chip, u8 mask,
+ unsigned long timeout,
+ wait_queue_head_t *queue)
+{
+ unsigned long stop;
+ u8 status;
+
+ /* check current status */
+ status = tcm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ stop = jiffies + timeout;
+ do {
+ msleep(TCM_TIMEOUT);
+ status = tcm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+
+ return -ETIME;
+}
+
+static int recv_data(struct tcm_chip *chip, u8 *buf, size_t count)
+{
+ int ret;
+ int size = 0, burstcnt;
+
+ while (size < count && wait_for_stat(chip,
+ TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue) == 0) {
+ burstcnt = get_burstcount(chip);
+
+ if (burstcnt < 0) {
+ dev_err(chip->dev, "Unable to read burstcount\n");
+ return burstcnt;
+ }
+
+ for (; burstcnt > 0 && size < count; burstcnt--) {
+ ret = tcm_tis_readb(chip->dev,
+ TCM_DATA_FIFO(chip->vendor.locality),
+ &buf[size]);
+ tcm_dbg("TCM-dbg: buf[%d]: 0x%x\n", size, buf[size]);
+ size++;
+ }
+ }
+
+ return size;
+}
+
+static int tcm_tis_recv(struct tcm_chip *chip, u8 *buf, size_t count)
+{
+ int size = 0;
+ int expected, status;
+ unsigned long stop;
+
+ if (count < TCM_HEADER_SIZE) {
+ dev_err(chip->dev, "read size is to small: %d\n", (u32)(count));
+ size = -EIO;
+ goto out;
+ }
+
+ /* read first 10 bytes, including tag, paramsize, and result */
+ size = recv_data(chip, buf, TCM_HEADER_SIZE);
+ if (size < TCM_HEADER_SIZE) {
+ dev_err(chip->dev, "Unable to read header\n");
+ goto out;
+ }
+
+ expected = be32_to_cpu(*(__be32 *)(buf + 2));
+ if (expected > count) {
+ dev_err(chip->dev, "Expected data count\n");
+ size = -EIO;
+ goto out;
+ }
+
+ size += recv_data(chip, &buf[TCM_HEADER_SIZE],
+ expected - TCM_HEADER_SIZE);
+ if (size < expected) {
+ dev_err(chip->dev, "Unable to read remainder of result\n");
+ size = -ETIME;
+ goto out;
+ }
+
+ wait_for_stat(chip, TCM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+
+ stop = jiffies + chip->vendor.timeout_c;
+ do {
+ msleep(TCM_TIMEOUT);
+ status = tcm_tis_status(chip);
+ if ((status & TCM_STS_DATA_AVAIL) == 0)
+ break;
+
+ } while (time_before(jiffies, stop));
+
+ status = tcm_tis_status(chip);
+ if (status & TCM_STS_DATA_AVAIL) { /* retry? */
+ dev_err(chip->dev, "Error left over data\n");
+ size = -EIO;
+ goto out;
+ }
+
+out:
+ tcm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ if (size < 0)
+ tcm_handle_err(chip);
+ return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tcm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tcm_tis_send(struct tcm_chip *chip, u8 *buf, size_t len)
+{
+ int rc, status, burstcnt;
+ size_t count = 0;
+ u32 ordinal;
+ unsigned long stop;
+ int send_again = 0;
+
+tcm_tis_send_again:
+ count = 0;
+ if (request_locality(chip, 0) < 0) {
+ dev_err(chip->dev, "send, tcm is busy\n");
+ return -EBUSY;
+ }
+ status = tcm_tis_status(chip);
+
+ if ((status & TCM_STS_COMMAND_READY) == 0) {
+ tcm_tis_ready(chip);
+ if (wait_for_stat(chip, TCM_STS_COMMAND_READY,
+ chip->vendor.timeout_b, &chip->vendor.int_queue) < 0) {
+ dev_err(chip->dev, "send, tcm wait time out1\n");
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+
+ while (count < len - 1) {
+ burstcnt = get_burstcount(chip);
+ if (burstcnt < 0) {
+ dev_err(chip->dev, "Unable to read burstcount\n");
+ rc = burstcnt;
+ goto out_err;
+ }
+ for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+ tcm_tis_writeb(chip->dev,
+ TCM_DATA_FIFO(chip->vendor.locality), buf[count]);
+ count++;
+ }
+
+ wait_for_stat(chip, TCM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ }
+
+ /* write last byte */
+ tcm_tis_writeb(chip->dev,
+ TCM_DATA_FIFO(chip->vendor.locality), buf[count]);
+
+ wait_for_stat(chip, TCM_STS_VALID,
+ chip->vendor.timeout_c, &chip->vendor.int_queue);
+ stop = jiffies + chip->vendor.timeout_c;
+ do {
+ msleep(TCM_TIMEOUT);
+ status = tcm_tis_status(chip);
+ if ((status & TCM_STS_DATA_EXPECT) == 0)
+ break;
+
+ } while (time_before(jiffies, stop));
+
+ if ((status & TCM_STS_DATA_EXPECT) != 0) {
+ dev_err(chip->dev, "send, tcm expect data\n");
+ rc = -EIO;
+ goto out_err;
+ }
+
+ /* go and do it */
+ tcm_tis_writeb(chip->dev, TCM_STS(chip->vendor.locality), TCM_STS_GO);
+
+ ordinal = be32_to_cpu(*((__be32 *)(buf + 6)));
+ if (wait_for_stat(chip, TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ tcm_calc_ordinal_duration(chip, ordinal),
+ &chip->vendor.read_queue) < 0) {
+ dev_err(chip->dev, "send, tcm wait time out2\n");
+ rc = -ETIME;
+ goto out_err;
+ }
+
+ return len;
+
+out_err:
+ tcm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ tcm_handle_err(chip);
+ if (send_again++ < 3) {
+ goto tcm_tis_send_again;
+ }
+
+ dev_err(chip->dev, "kylin send, err: %d\n", rc);
+ return rc;
+}
+
+static struct file_operations tis_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tcm_open,
+ .read = tcm_read,
+ .write = tcm_write,
+ .release = tcm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tcm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tcm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tcm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tcm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tcm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tcm_show_temp_deactivated,
+ NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tcm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tcm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_active.attr,
+ &dev_attr_owned.attr,
+ &dev_attr_temp_deactivated.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+ .attrs = tis_attrs
+};
+
+static struct tcm_vendor_specific tcm_tis = {
+ .status = tcm_tis_status,
+ .recv = tcm_tis_recv,
+ .send = tcm_tis_send,
+ .cancel = tcm_tis_ready,
+ .req_complete_mask = TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ .req_complete_val = TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ .req_canceled = TCM_STS_COMMAND_READY,
+ .attr_group = &tis_attr_grp,
+ .miscdev = {
+ .fops = &tis_ops,
+ },
+};
+
+static struct tcm_chip *chip;
+static int tcm_tis_spi_probe(struct spi_device *spi)
+{
+ int ret;
+ u8 revid;
+ u32 vendor, intfcaps;
+ struct tcm_tis_spi_phy *phy;
+ struct chip_data *spi_chip;
+
+ pr_info("TCM(ky): __func__(v=%d) ..\n",
+ 10);
+
+ tcm_dbg("TCM-dbg: %s/%d, enter\n", __func__, __LINE__);
+ phy = devm_kzalloc(&spi->dev, sizeof(struct tcm_tis_spi_phy),
+ GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+ if (!phy->iobuf)
+ return -ENOMEM;
+
+ phy->spi_device = spi;
+ init_completion(&phy->ready);
+
+ tcm_dbg("TCM-dbg: %s/%d\n", __func__, __LINE__);
+ /* init spi dev */
+ spi->chip_select = 0; /* cs0 */
+ spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ spi->max_speed_hz = spi->max_speed_hz ? : 24000000;
+ spi_setup(spi);
+
+ spi_chip = spi_get_ctldata(spi);
+ if (!spi_chip) {
+ pr_err("There was wrong in spi master\n");
+ return -ENODEV;
+ }
+ /* tcm does not support interrupt mode, we use poll mode instead. */
+ spi_chip->poll_mode = 1;
+
+ tcm_dbg("TCM-dbg: %s/%d\n", __func__, __LINE__);
+ /* regiter tcm hw */
+ chip = tcm_register_hardware(&spi->dev, &tcm_tis);
+ if (!chip) {
+ dev_err(chip->dev, "tcm register hardware err\n");
+ return -ENODEV;
+ }
+
+ dev_set_drvdata(chip->dev, phy);
+
+ /**
+ * phytium2000a4 spi controller's clk clk level is unstable,
+ * so it is solved by using the low level of gpio output.
+ **/
+ if (is_ft_all() && (spi->chip_select == 0)) {
+ /* reuse conf reg base */
+ reuse_conf_reg = ioremap(REUSE_CONF_REG_BASE, 0x10);
+ if (!reuse_conf_reg) {
+ dev_err(&spi->dev, "Failed to ioremap reuse conf reg\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ /* gpio1 a5 base addr */
+ gpio1_a5 = ioremap(REUSE_GPIO1_A5_BASE, 0x10);
+ if (!gpio1_a5) {
+ dev_err(&spi->dev, "Failed to ioremap gpio1 a5\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ /* reuse cs0 to gpio1_a5 */
+ iowrite32((ioread32(reuse_conf_reg) | 0xFFFF0) & 0xFFF9004F,
+ reuse_conf_reg);
+ /* set gpio1 a5 to output */
+ iowrite32(0x20, gpio1_a5 + 0x4);
+ }
+
+ tcm_dbg("TCM-dbg: %s/%d\n",
+ __func__, __LINE__);
+ ret = tcm_tis_readl(chip->dev, TCM_DID_VID(0), &vendor);
+ if (ret < 0)
+ goto out_err;
+
+ tcm_dbg("TCM-dbg: %s/%d, vendor: 0x%x\n",
+ __func__, __LINE__, vendor);
+ if ((vendor & 0xffff) != 0x19f5 && (vendor & 0xffff) != 0x1B4E) {
+ dev_err(chip->dev, "there is no Nationz TCM on you computer\n");
+ goto out_err;
+ }
+
+ ret = tcm_tis_readb(chip->dev, TCM_RID(0), &revid);
+ tcm_dbg("TCM-dbg: %s/%d, revid: 0x%x\n",
+ __func__, __LINE__, revid);
+ if (ret < 0)
+ goto out_err;
+ dev_info(chip->dev, "kylin: 2019-09-21 1.2 TCM "
+ "(device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, revid);
+
+ /* Default timeouts */
+ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+ tcm_dbg("TCM-dbg: %s/%d\n",
+ __func__, __LINE__);
+ /* Figure out the capabilities */
+ ret = tcm_tis_readl(chip->dev,
+ TCM_INTF_CAPS(chip->vendor.locality), &intfcaps);
+ if (ret < 0)
+ goto out_err;
+
+ tcm_dbg("TCM-dbg: %s/%d, intfcaps: 0x%x\n",
+ __func__, __LINE__, intfcaps);
+ if (request_locality(chip, 0) != 0) {
+ dev_err(chip->dev, "tcm request_locality err\n");
+ ret = -ENODEV;
+ goto out_err;
+ }
+
+ INIT_LIST_HEAD(&chip->vendor.list);
+ spin_lock(&tis_lock);
+ list_add(&chip->vendor.list, &tis_chips);
+ spin_unlock(&tis_lock);
+
+ tcm_get_timeouts(chip);
+ tcm_startup(chip);
+
+ tcm_dbg("TCM-dbg: %s/%d, exit\n", __func__, __LINE__);
+ return 0;
+
+out_err:
+ if (is_ft_all()) {
+ if (reuse_conf_reg)
+ iounmap(reuse_conf_reg);
+ if (gpio1_a5)
+ iounmap(gpio1_a5);
+ }
+ tcm_dbg("TCM-dbg: %s/%d, error\n", __func__, __LINE__);
+ dev_set_drvdata(chip->dev, chip);
+ tcm_remove_hardware(chip->dev);
+
+ return ret;
+}
+
+static int tcm_tis_spi_remove(struct spi_device *dev)
+{
+ if (is_ft_all()) {
+ if (reuse_conf_reg)
+ iounmap(reuse_conf_reg);
+ if (gpio1_a5)
+ iounmap(gpio1_a5);
+ }
+
+ dev_info(&dev->dev, "%s\n", __func__);
+ dev_set_drvdata(chip->dev, chip);
+ tcm_remove_hardware(&dev->dev);
+
+ return 0;
+}
+
+static const struct acpi_device_id tcm_tis_spi_acpi_match[] = {
+ {"TCMS0001", 0},
+ {"SMO0768", 0},
+ {"ZIC0601", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, tcm_tis_spi_acpi_match);
+
+static const struct spi_device_id tcm_tis_spi_id_table[] = {
+ {"SMO0768", 0},
+ {"ZIC0601", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, tcm_tis_spi_id_table);
+
+static struct spi_driver tcm_tis_spi_drv = {
+ .driver = {
+ .name = "tcm_tis_spi",
+ .acpi_match_table = ACPI_PTR(tcm_tis_spi_acpi_match),
+ },
+ .id_table = tcm_tis_spi_id_table,
+ .probe = tcm_tis_spi_probe,
+ .remove = tcm_tis_spi_remove,
+};
+
+#if 1
+module_spi_driver(tcm_tis_spi_drv);
+#else/*0*/
+
+static int __init __spi_driver_init(void)
+{
+ pr_info("TCM(ky): __init __func__(ver=%2d)\n",
+ 10);
+ return spi_register_driver(&tcm_tis_spi_drv);
+}
+
+static void __exit __spi_driver_exit(void)
+{
+ pr_info("TCM(ky): __exit __func__\n");
+ spi_unregister_driver(&tcm_tis_spi_drv);
+}
+
+module_init(__spi_driver_init);
+module_exit(__spi_driver_exit);
+#endif/*0*/
+
+MODULE_AUTHOR("xiongxin<xiongxin(a)tj.kylinos.cn>");
+MODULE_DESCRIPTION("TCM Driver Base Spi");
+MODULE_VERSION("6.1.0.2");
+MODULE_LICENSE("GPL");
--
2.23.0
1
1
23 Feb '21
1
0
23 Feb '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
Introducing a feature of CPU PARK in order to save time
of cpus down and up during kexec, which may cost 250ms of
per cpu's down and 30ms of up.
As a result, for 128 cores, it costs more than 30 seconds
to down and up cpus during kexec. Think about 256 cores and more.
CPU PARK is a state that cpu power-on and staying in spin loop, polling
for exit chances, such as writing exit address.
Reserving a block of memory, to fill with cpu park text section,
exit address and park-magic-flag of each cpu. In implementation,
reserved one page for one cpu core.
Cpus going to park state instead of down in machine_shutdown().
Cpus going out of park state in smp_init instead of brought up.
One of cpu park sections in pre-reserved memory blocks,:
+--------------+
+ exit address +
+--------------+
+ park magic +
+--------------+
+ park codes +
+ . +
+ . +
+ . +
+--------------+
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/Kconfig | 12 ++
arch/arm64/include/asm/kexec.h | 6 +
arch/arm64/include/asm/smp.h | 15 +++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/cpu-park.S | 59 ++++++++++
arch/arm64/kernel/machine_kexec.c | 2 +-
arch/arm64/kernel/process.c | 4 +
arch/arm64/kernel/smp.c | 229 ++++++++++++++++++++++++++++++++++++++
arch/arm64/mm/init.c | 55 +++++++++
9 files changed, 382 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/cpu-park.S
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b9c5654..0885668 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -345,6 +345,18 @@ config KASAN_SHADOW_OFFSET
default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
+config ARM64_CPU_PARK
+ bool "Support CPU PARK on kexec"
+ depends on SMP
+ depends on KEXEC_CORE
+ help
+ This enables support for CPU PARK feature in
+ order to save time of cpu down to up.
+ CPU park is a state through kexec, spin loop
+ instead of cpu die before jumping to new kernel,
+ jumping out from loop to new kernel entry in
+ smp_init.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 79909ae..a133889 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -36,6 +36,11 @@
#define CRASH_ADDR_HIGH_MAX MEMBLOCK_ALLOC_ACCESSIBLE
+#ifdef CONFIG_ARM64_CPU_PARK
+/* CPU park state flag: "park" */
+#define PARK_MAGIC 0x7061726b
+#endif
+
#ifndef __ASSEMBLY__
/**
@@ -104,6 +109,7 @@ static inline void crash_post_resume(void) {}
#ifdef CONFIG_KEXEC_CORE
extern void __init reserve_crashkernel(void);
#endif
+void machine_kexec_mask_interrupts(void);
#ifdef CONFIG_KEXEC_FILE
#define ARCH_HAS_KIMAGE_ARCH
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 2e7f529..8c5d2d6 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -145,6 +145,21 @@ bool cpus_are_stuck_in_kernel(void);
extern void crash_smp_send_stop(void);
extern bool smp_crash_stop_failed(void);
+#ifdef CONFIG_ARM64_CPU_PARK
+#define PARK_SECTION_SIZE 1024
+struct cpu_park_info {
+ /* Physical address of reserved park memory. */
+ unsigned long start;
+ /* park reserve mem len should be PARK_SECTION_SIZE * NR_CPUS */
+ unsigned long len;
+ /* Virtual address of reserved park memory. */
+ unsigned long start_v;
+};
+extern struct cpu_park_info park_info;
+extern void enter_cpu_park(unsigned long text, unsigned long exit);
+extern void do_cpu_park(unsigned long exit);
+extern int kexec_smp_send_park(void);
+#endif
#endif /* ifndef __ASSEMBLY__ */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2621d5c..60478d2 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \
cpu-reset.o
+obj-$(CONFIG_ARM64_CPU_PARK) += cpu-park.o
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o
arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
diff --git a/arch/arm64/kernel/cpu-park.S b/arch/arm64/kernel/cpu-park.S
new file mode 100644
index 0000000..10c685c
--- /dev/null
+++ b/arch/arm64/kernel/cpu-park.S
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * CPU park routines
+ *
+ * Copyright (C) 2020 Huawei Technologies., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/sysreg.h>
+#include <asm/virt.h>
+
+.text
+.pushsection .idmap.text, "awx"
+
+/* cpu park helper in idmap section */
+SYM_CODE_START(enter_cpu_park)
+ /* Clear sctlr_el1 flags. */
+ mrs x12, sctlr_el1
+ mov_q x13, SCTLR_ELx_FLAGS
+ bic x12, x12, x13
+ pre_disable_mmu_workaround
+ msr sctlr_el1, x12 /* disable mmu */
+ isb
+
+ mov x18, x0
+ mov x0, x1 /* secondary_entry addr */
+ br x18 /* call do_cpu_park of each cpu */
+SYM_CODE_END(enter_cpu_park)
+
+.popsection
+
+SYM_CODE_START(do_cpu_park)
+ ldr x18, =PARK_MAGIC /* magic number "park" */
+ add x1, x0, #8
+ str x18, [x1] /* set on-park flag */
+ dc civac, x1 /* flush cache of "park" */
+ dsb nsh
+ isb
+
+.Lloop:
+ wfe
+ isb
+ ldr x19, [x0]
+ cmp x19, #0 /* test secondary_entry */
+ b.eq .Lloop
+
+ ic iallu /* invalidate the local I-cache */
+ dsb nsh
+ isb
+
+ br x19 /* jump to secondary_entry */
+SYM_CODE_END(do_cpu_park)
+
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index a0b144c..f47ce96 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -213,7 +213,7 @@ void machine_kexec(struct kimage *kimage)
BUG(); /* Should never get here. */
}
-static void machine_kexec_mask_interrupts(void)
+void machine_kexec_mask_interrupts(void)
{
unsigned int i;
struct irq_desc *desc;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 73e3b32..10cffee 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -146,6 +146,10 @@ void arch_cpu_idle_dead(void)
*/
void machine_shutdown(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (kexec_smp_send_park() == 0)
+ return;
+#endif
smp_shutdown_nonboot_cpus(reboot_cpu);
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 18e9727..bc475d5 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -32,6 +32,8 @@
#include <linux/irq_work.h>
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
+#include <linux/console.h>
+
#include <linux/kvm_host.h>
#include <asm/alternative.h>
@@ -93,6 +95,167 @@ static inline int op_cpu_kill(unsigned int cpu)
}
#endif
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_section {
+ unsigned long exit; /* exit address of park look */
+ unsigned long magic; /* maigc represent park state */
+ char text[0]; /* text section of park */
+};
+
+static int mmap_cpu_park_mem(void)
+{
+ if (!park_info.start)
+ return -ENOMEM;
+
+ if (park_info.start_v)
+ return 0;
+
+ park_info.start_v = (unsigned long)__ioremap(park_info.start,
+ park_info.len,
+ PAGE_KERNEL_EXEC);
+ if (!park_info.start_v) {
+ pr_warn("map park memory failed.");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline unsigned long cpu_park_section_v(unsigned int cpu)
+{
+ return park_info.start_v + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+static inline unsigned long cpu_park_section_p(unsigned int cpu)
+{
+ return park_info.start + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+/*
+ * Write the secondary_entry to exit section of park state.
+ * Then the secondary cpu will jump straight into the kernel
+ * by the secondary_entry.
+ */
+static int write_park_exit(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_text;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_exit = &park_section->exit;
+ park_text = (unsigned long *)park_section->text;
+ pr_debug("park_text 0x%lx : 0x%lx, do_cpu_park text 0x%lx : 0x%lx",
+ (unsigned long)park_text, *park_text,
+ (unsigned long)do_cpu_park,
+ *(unsigned long *)do_cpu_park);
+
+ /*
+ * Test first 8 bytes to determine
+ * whether needs to write cpu park exit.
+ */
+ if (*park_text == *(unsigned long *)do_cpu_park) {
+ writeq_relaxed(__pa_symbol(secondary_entry), park_exit);
+ __flush_dcache_area((__force void *)park_exit,
+ sizeof(unsigned long));
+ flush_icache_range((unsigned long)park_exit,
+ (unsigned long)(park_exit + 1));
+ sev();
+ dsb(sy);
+ isb();
+
+ pr_debug("Write cpu %u secondary entry 0x%lx to 0x%lx.",
+ cpu, *park_exit, (unsigned long)park_exit);
+ pr_info("Boot cpu %u from PARK state.", cpu);
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+/* Install cpu park sections for the specific cpu. */
+static int install_cpu_park(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_magic;
+ unsigned long park_text_len;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ pr_debug("Install cpu park on cpu %u park exit 0x%lx park text 0x%lx",
+ cpu, (unsigned long)park_section,
+ (unsigned long)(park_section->text));
+
+ park_exit = &park_section->exit;
+ park_magic = &park_section->magic;
+ park_text_len = PARK_SECTION_SIZE - sizeof(struct cpu_park_section);
+
+ *park_exit = 0UL;
+ *park_magic = 0UL;
+ memcpy((void *)park_section->text, do_cpu_park, park_text_len);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int uninstall_cpu_park(unsigned int cpu)
+{
+ unsigned long park_section;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = cpu_park_section_v(cpu);
+ memset((void *)park_section, 0, PARK_SECTION_SIZE);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int cpu_wait_park(unsigned int cpu)
+{
+ long timeout;
+ struct cpu_park_section *park_section;
+
+ volatile unsigned long *park_magic;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_magic = &park_section->magic;
+
+ timeout = USEC_PER_SEC;
+ while (*park_magic != PARK_MAGIC && timeout--)
+ udelay(1);
+
+ if (timeout > 0)
+ pr_debug("cpu %u park done.", cpu);
+ else
+ pr_err("cpu %u park failed.", cpu);
+
+ return *park_magic == PARK_MAGIC;
+}
+
+static void cpu_park(unsigned int cpu)
+{
+ unsigned long park_section_p;
+ unsigned long park_exit_phy;
+ unsigned long do_park;
+ typeof(enter_cpu_park) *park;
+
+ park_section_p = cpu_park_section_p(cpu);
+ park_exit_phy = park_section_p;
+ pr_debug("Go to park cpu %u exit address 0x%lx", cpu, park_exit_phy);
+
+ do_park = park_section_p + sizeof(struct cpu_park_section);
+ park = (void *)__pa_symbol(enter_cpu_park);
+
+ cpu_install_idmap();
+ park(do_park, park_exit_phy);
+ unreachable();
+}
+#endif
/*
* Boot a secondary CPU, and assign it the specified idle task.
@@ -102,6 +265,10 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle)
{
const struct cpu_operations *ops = get_cpu_ops(cpu);
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (write_park_exit(cpu) == 0)
+ return 0;
+#endif
if (ops->cpu_boot)
return ops->cpu_boot(cpu);
@@ -131,6 +298,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
@@ -844,10 +1014,30 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void)
{
+ int cpu;
+ const struct cpu_operations *ops = NULL;
+
set_cpu_online(smp_processor_id(), false);
local_daif_mask();
sdei_mask_local_cpu();
+
+#ifdef CONFIG_ARM64_CPU_PARK
+ /*
+ * Go to cpu park state.
+ * Otherwise go to cpu die.
+ */
+ cpu = smp_processor_id();
+ if (kexec_in_progress && park_info.start_v) {
+ machine_kexec_mask_interrupts();
+ cpu_park(cpu);
+
+ ops = get_cpu_ops(cpu);
+ if (ops && ops->cpu_die)
+ ops->cpu_die(cpu);
+ }
+#endif
+
cpu_park_loop();
}
@@ -1053,6 +1243,45 @@ void smp_send_stop(void)
sdei_mask_local_cpu();
}
+#ifdef CONFIG_ARM64_CPU_PARK
+int kexec_smp_send_park(void)
+{
+ unsigned long cpu;
+
+ if (WARN_ON(!kexec_in_progress)) {
+ pr_crit("%s called not in kexec progress.", __func__);
+ return -EPERM;
+ }
+
+ if (mmap_cpu_park_mem() != 0) {
+ pr_info("no cpuparkmem, goto normal way.");
+ return -EPERM;
+ }
+
+ local_irq_disable();
+
+ if (num_online_cpus() > 1) {
+ cpumask_t mask;
+
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+
+ for_each_cpu(cpu, &mask)
+ install_cpu_park(cpu);
+ smp_cross_call(&mask, IPI_CPU_STOP);
+
+ /* Wait for other CPUs to park */
+ for_each_cpu(cpu, &mask)
+ cpu_wait_park(cpu);
+ pr_info("smp park other cpus done\n");
+ }
+
+ sdei_mask_local_cpu();
+
+ return 0;
+}
+#endif
+
#ifdef CONFIG_KEXEC_CORE
void crash_smp_send_stop(void)
{
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 794f992..d01259c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -236,6 +236,57 @@ static void __init fdt_enforce_memory_region(void)
memblock_add(usable_rgns[1].base, usable_rgns[1].size);
}
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_info park_info = {
+ .start = 0,
+ .len = PARK_SECTION_SIZE * NR_CPUS,
+ .start_v = 0,
+};
+
+static int __init parse_park_mem(char *p)
+{
+ if (!p)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(memparse(p, NULL));
+ if (park_info.start == 0)
+ pr_info("cpu park mem params[%s]", p);
+
+ return 0;
+}
+early_param("cpuparkmem", parse_park_mem);
+
+static int __init reserve_park_mem(void)
+{
+ if (park_info.start == 0 || park_info.len == 0)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(park_info.start);
+ park_info.len = PAGE_ALIGN(park_info.len);
+
+ if (!memblock_is_region_memory(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region is not memory!");
+ goto out;
+ }
+
+ if (memblock_is_region_reserved(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region overlaps reserved memory!");
+ goto out;
+ }
+
+ memblock_remove(park_info.start, park_info.len);
+ pr_info("cpu park mem reserved: 0x%016lx - 0x%016lx (%ld MB)",
+ park_info.start, park_info.start + park_info.len,
+ park_info.len >> 20);
+
+ return 0;
+out:
+ park_info.start = 0;
+ park_info.len = 0;
+ return -EINVAL;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -357,6 +408,10 @@ void __init arm64_memblock_init(void)
reserve_crashkernel();
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
--
2.9.5
2
3
22 Feb '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
In normal kexec, relocating kernel may cost 5 ~ 10 seconds, to
copy all segments from vmalloced memory to kernel boot memory,
because of disabled mmu.
We introduce quick kexec to save time of copying memory as above,
just like kdump(kexec on crash), by using reserved memory
"Quick Kexec".
Constructing quick kimage as the same as crash kernel,
then simply copy all segments of kimage to reserved memroy.
We also add this support in syscall kexec_load using flags
of KEXEC_QUICK.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/Kconfig | 10 ++++++++++
include/linux/ioport.h | 1 +
include/linux/kexec.h | 11 ++++++++++-
include/uapi/linux/kexec.h | 1 +
kernel/kexec.c | 10 ++++++++++
kernel/kexec_core.c | 42 +++++++++++++++++++++++++++++++++---------
6 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 2592b4b..7811eee 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -18,6 +18,16 @@ config KEXEC_CORE
select CRASH_CORE
bool
+config QUICK_KEXEC
+ bool "Support for quick kexec"
+ depends on KEXEC_CORE
+ help
+ It uses pre-reserved memory to accelerate kexec, just like
+ crash kexec, loads new kernel and initrd to reserved memory,
+ and boots new kernel on that memory. It will save the time
+ of relocating kernel.
+
+
config KEXEC_ELF
bool
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 5135d4b..84a716f 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -139,6 +139,7 @@ enum {
IORES_DESC_DEVICE_PRIVATE_MEMORY = 6,
IORES_DESC_RESERVED = 7,
IORES_DESC_SOFT_RESERVED = 8,
+ IORES_DESC_QUICK_KEXEC = 9,
};
/*
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f301f2f..7fff410 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -269,9 +269,10 @@ struct kimage {
unsigned long control_page;
/* Flags to indicate special processing */
- unsigned int type : 1;
+ unsigned int type : 2;
#define KEXEC_TYPE_DEFAULT 0
#define KEXEC_TYPE_CRASH 1
+#define KEXEC_TYPE_QUICK 2
unsigned int preserve_context : 1;
/* If set, we are using file mode kexec syscall */
unsigned int file_mode:1;
@@ -331,6 +332,11 @@ extern int kexec_load_disabled;
#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)
#endif
+#ifdef CONFIG_QUICK_KEXEC
+#undef KEXEC_FLAGS
+#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_QUICK)
+#endif
+
/* List of defined/legal kexec file flags */
#define KEXEC_FILE_FLAGS (KEXEC_FILE_UNLOAD | KEXEC_FILE_ON_CRASH | \
KEXEC_FILE_NO_INITRAMFS)
@@ -338,6 +344,9 @@ extern int kexec_load_disabled;
/* Location of a reserved region to hold the crash kernel.
*/
extern note_buf_t __percpu *crash_notes;
+#ifdef CONFIG_QUICK_KEXEC
+extern struct resource quick_kexec_res;
+#endif
/* flag to track if kexec reboot is in progress */
extern bool kexec_in_progress;
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 05669c8..d891d80 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -12,6 +12,7 @@
/* kexec flags for different usage scenarios */
#define KEXEC_ON_CRASH 0x00000001
#define KEXEC_PRESERVE_CONTEXT 0x00000002
+#define KEXEC_QUICK 0x00000004
#define KEXEC_ARCH_MASK 0xffff0000
/*
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c82c6c0..4acc909 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -44,6 +44,9 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
int ret;
struct kimage *image;
bool kexec_on_panic = flags & KEXEC_ON_CRASH;
+#ifdef CONFIG_QUICK_KEXEC
+ bool kexec_on_quick = flags & KEXEC_QUICK;
+#endif
if (kexec_on_panic) {
/* Verify we have a valid entry point */
@@ -69,6 +72,13 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
image->type = KEXEC_TYPE_CRASH;
}
+#ifdef CONFIG_QUICK_KEXEC
+ if (kexec_on_quick) {
+ image->control_page = quick_kexec_res.start;
+ image->type = KEXEC_TYPE_QUICK;
+ }
+#endif
+
ret = sanity_check_segment_list(image);
if (ret)
goto out_free_image;
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 2ca8875..c7e2aa2 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -53,6 +53,17 @@ note_buf_t __percpu *crash_notes;
/* Flag to indicate we are going to kexec a new kernel */
bool kexec_in_progress = false;
+/* Resource for quick kexec */
+#ifdef CONFIG_QUICK_KEXEC
+struct resource quick_kexec_res = {
+ .name = "Quick kexec",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
+ .desc = IORES_DESC_QUICK_KEXEC
+};
+#endif
+
int kexec_should_crash(struct task_struct *p)
{
/*
@@ -396,8 +407,9 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
return pages;
}
-static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
- unsigned int order)
+static struct page *kimage_alloc_special_control_pages(struct kimage *image,
+ unsigned int order,
+ unsigned long end)
{
/* Control pages are special, they are the intermediaries
* that are needed while we copy the rest of the pages
@@ -427,7 +439,7 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
size = (1 << order) << PAGE_SHIFT;
hole_start = (image->control_page + (size - 1)) & ~(size - 1);
hole_end = hole_start + size - 1;
- while (hole_end <= crashk_res.end) {
+ while (hole_end <= end) {
unsigned long i;
cond_resched();
@@ -462,7 +474,6 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
return pages;
}
-
struct page *kimage_alloc_control_pages(struct kimage *image,
unsigned int order)
{
@@ -473,8 +484,15 @@ struct page *kimage_alloc_control_pages(struct kimage *image,
pages = kimage_alloc_normal_control_pages(image, order);
break;
case KEXEC_TYPE_CRASH:
- pages = kimage_alloc_crash_control_pages(image, order);
+ pages = kimage_alloc_special_control_pages(image, order,
+ crashk_res.end);
+ break;
+#ifdef CONFIG_QUICK_KEXEC
+ case KEXEC_TYPE_QUICK:
+ pages = kimage_alloc_special_control_pages(image, order,
+ quick_kexec_res.end);
break;
+#endif
}
return pages;
@@ -830,11 +848,12 @@ static int kimage_load_normal_segment(struct kimage *image,
return result;
}
-static int kimage_load_crash_segment(struct kimage *image,
+static int kimage_load_special_segment(struct kimage *image,
struct kexec_segment *segment)
{
- /* For crash dumps kernels we simply copy the data from
- * user space to it's destination.
+ /*
+ * For crash dumps kernels and quick kexec kernels
+ * we simply copy the data from user space to it's destination.
* We do things a page at a time for the sake of kmap.
*/
unsigned long maddr;
@@ -908,8 +927,13 @@ int kimage_load_segment(struct kimage *image,
result = kimage_load_normal_segment(image, segment);
break;
case KEXEC_TYPE_CRASH:
- result = kimage_load_crash_segment(image, segment);
+ result = kimage_load_special_segment(image, segment);
break;
+#ifdef CONFIG_QUICK_KEXEC
+ case KEXEC_TYPE_QUICK:
+ result = kimage_load_special_segment(image, segment);
+ break;
+#endif
}
return result;
--
2.9.5
2
3
bugfix for 20.03 @ 2021/02/22
Aichun Li (7):
netpoll: remove dev argument from netpoll_send_skb_on_dev()
netpoll: move netpoll_send_skb() out of line
netpoll: netpoll_send_skb() returns transmit status
netpoll: accept NULL np argument in netpoll_send_skb()
bonding: add an option to specify a delay between peer notifications
bonding: fix value exported by Netlink for peer_notif_delay
bonding: add documentation for peer_notif_delay
Akilesh Kailash (1):
dm snapshot: flush merged data before committing metadata
Al Viro (2):
don't dump the threads that had been already exiting when zapped.
dump_common_audit_data(): fix racy accesses to ->d_name
Aleksandr Nogikh (1):
netem: fix zero division in tabledist
Alexander Duyck (1):
tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
Alexander Lobakin (1):
skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
Alexey Dobriyan (2):
proc: change ->nlink under proc_subdir_lock
proc: fix lookup in /proc/net subdirectories after setns(2)
Alexey Kardashevskiy (1):
serial_core: Check for port state when tty is in error state
Amit Cohen (1):
mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
Andy Shevchenko (2):
device property: Keep secondary firmware node secondary by type
device property: Don't clear secondary pointer for shared primary
firmware node
Antoine Tenart (6):
netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING
traversal
net: ip6_gre: set dev->hard_header_len when using header_ops
net-sysfs: take the rtnl lock when storing xps_cpus
net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
net-sysfs: take the rtnl lock when storing xps_rxqs
net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
Ard Biesheuvel (3):
efivarfs: revert "fix memory leak in efivarfs_create()"
arm64, mm, efi: Account for GICv3 LPI tables in static memblock
reserve table
efi/arm: Revert "Defer persistent reservations until after
paging_init()"
Arjun Roy (1):
tcp: Prevent low rmem stalls with SO_RCVLOWAT.
Arnaldo Carvalho de Melo (1):
perf scripting python: Avoid declaring function pointers with a
visibility attribute
Axel Lin (1):
ASoC: msm8916-wcd-digital: Select REGMAP_MMIO to fix build error
Aya Levin (1):
net: ipv6: Validate GSO SKB before finish IPv6 processing
Bart Van Assche (1):
scsi: scsi_transport_spi: Set RQF_PM for domain validation commands
Bharat Gooty (1):
PCI: iproc: Fix out-of-bound array accesses
Bixuan Cui (2):
mmap: fix a compiling error for 'MAP_CHECKNODE'
powerpc: fix a compiling error for 'access_ok'
Bjorn Helgaas (1):
PCI: Bounds-check command-line resource alignment requests
Björn Töpel (1):
ixgbe: avoid premature Rx buffer reuse
Boqun Feng (1):
fcntl: Fix potential deadlock in send_sig{io, urg}()
Boris Protopopov (1):
Convert trailing spaces and periods in path components
Brian Foster (1):
xfs: flush new eof page on truncate to avoid post-eof corruption
Calum Mackay (1):
lockd: don't use interval-based rebinding over TCP
Chen Zhou (1):
selinux: Fix error return code in sel_ib_pkey_sid_slow()
Chenguangli (1):
scsi/hifc:Fix the bug that the system may be oops during unintall hifc
module.
Cheng Lin (1):
nfs_common: need lock during iterate through the list
Christoph Hellwig (2):
nbd: fix a block_device refcount leak in nbd_release
xfs: fix a missing unlock on error in xfs_fs_map_blocks
Chunguang Xu (1):
ext4: fix a memory leak of ext4_free_data
Chunyan Zhang (1):
tick/common: Touch watchdog in tick_unfreeze() on all CPUs
Colin Ian King (1):
PCI: Fix overflow in command-line resource alignment requests
Cong Wang (1):
erspan: fix version 1 check in gre_parse_header()
Damien Le Moal (1):
null_blk: Fix zone size initialization
Dan Carpenter (1):
futex: Don't enable IRQs unconditionally in put_pi_state()
Daniel Scally (1):
Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources
walks"
Darrick J. Wong (12):
xfs: fix realtime bitmap/summary file truncation when growing rt
volume
xfs: don't free rt blocks when we're doing a REMAP bunmapi call
xfs: set xefi_discard when creating a deferred agfl free log intent
item
xfs: fix scrub flagging rtinherit even if there is no rt device
xfs: fix flags argument to rmap lookup when converting shared file
rmaps
xfs: set the unwritten bit in rmap lookup flags in
xchk_bmap_get_rmapextents
xfs: fix rmap key and record comparison functions
xfs: fix brainos in the refcount scrubber's rmap fragment processor
vfs: remove lockdep bogosity in __sb_start_write
xfs: fix the minrecs logic when dealing with inode root child blocks
xfs: strengthen rmap record flags checking
xfs: revert "xfs: fix rmap key and record comparison functions"
Dave Wysochanski (1):
NFS4: Fix use-after-free in trace_event_raw_event_nfs4_set_lock
Dexuan Cui (1):
ACPI: scan: Harden acpi_device_add() against device ID overflows
Dinghao Liu (4):
ext4: fix error handling code in add_new_gdb
net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
net/mlx5e: Fix two double free cases
netfilter: nf_nat: Fix memleak in nf_nat_init
Dongdong Wang (1):
lwt: Disable BH too in run_lwt_bpf()
Dongli Zhang (1):
page_frag: Recover from memory pressure
Douglas Gilbert (1):
sgl_alloc_order: fix memory leak
Eddy Wu (1):
fork: fix copy_process(CLONE_PARENT) race with the exiting
->real_parent
Eran Ben Elisha (1):
net/mlx5: Fix wrong address reclaim when command interface is down
Eric Auger (1):
vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
Eric Biggers (1):
ext4: fix leaking sysfs kobject after failed mount
Eric Dumazet (4):
tcp: select sane initial rcvq_space.space for big MSS
net: avoid 32 x truesize under-estimation for tiny skbs
net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
net_sched: reject silly cell_log in qdisc_get_rtab()
Fang Lijun (3):
arm64/ascend: mm: Add MAP_CHECKNODE flag to check node hugetlb
arm64/ascend: mm: Fix arm32 compile warnings
arm64/ascend: mm: Fix hugetlb check node error
Fangrui Song (1):
arm64: Change .weak to SYM_FUNC_START_WEAK_PI for
arch/arm64/lib/mem*.S
Florian Fainelli (1):
net: Have netpoll bring-up DSA management interface
Florian Westphal (4):
netfilter: nf_tables: avoid false-postive lockdep splat
netfilter: xt_RATEEST: reject non-null terminated string from
userspace
net: ip: always refragment ip defragmented packets
net: fix pmtu check in nopmtudisc mode
Gabriel Krisman Bertazi (2):
blk-cgroup: Fix memleak on error path
blk-cgroup: Pre-allocate tree node on blkg_conf_prep
George Spelvin (1):
random32: make prandom_u32() output unpredictable
Gerald Schaefer (1):
mm/userfaultfd: do not access vma->vm_mm after calling
handle_userfault()
Guillaume Nault (4):
ipv4: Fix tos mask in inet_rtm_getroute()
ipv4: Ignore ECN bits for fib lookups in fib_compute_spec_dst()
netfilter: rpfilter: mask ecn bits before fib lookup
udp: mask TOS bits in udp_v4_early_demux()
Hanjun Guo (1):
clocksource/drivers/arch_timer: Fix vdso_fix compile error for arm32
Hannes Reinecke (1):
dm: avoid filesystem lookup in dm_get_dev_t()
Hans de Goede (1):
ACPI: scan: Make acpi_bus_get_device() clear return pointer on error
Heiner Kallweit (1):
net: bridge: add missing counters to ndo_get_stats64 callback
Hoang Le (1):
tipc: fix NULL deref in tipc_link_xmit()
Huang Shijie (1):
lib/genalloc: fix the overflow when size is too big
Huang Ying (1):
mm: fix a race during THP splitting
Hugh Dickins (2):
mlock: fix unevictable_pgs event counts on THP
mm: fix check_move_unevictable_pages() on THP
Hui Wang (1):
ACPI: PNP: compare the string length in the matching_id()
Hyeongseok Kim (1):
dm verity: skip verity work if I/O error when system is shutting down
Ido Schimmel (2):
mlxsw: core: Fix memory leak on module removal
mlxsw: core: Use variable timeout for EMAD retries
Ilya Dryomov (1):
libceph: clear con->out_msg on Policy::stateful_server faults
Jakub Kicinski (1):
net: vlan: avoid leaks on register_vlan_dev() failures
Jamie Iles (1):
bonding: wait for sysfs kobject destruction before freeing struct
slave
Jan Kara (8):
ext4: Detect already used quota file early
ext4: fix bogus warning in ext4_update_dx_flag()
ext4: Protect superblock modifications with a buffer lock
ext4: fix deadlock with fs freezing and EA inodes
ext4: don't remount read-only with errors=continue on reboot
quota: Don't overflow quota file offsets
bfq: Fix computation of shallow depth
ext4: fix superblock checksum failure when setting password salt
Jann Horn (1):
mm, slub: consider rest of partial list if acquire_slab() fails
Jason A. Donenfeld (3):
netfilter: use actual socket sk rather than skb sk when routing harder
net: introduce skb_list_walk_safe for skb segment walking
net: skbuff: disambiguate argument and member for skb_list_walk_safe
helper
Jeff Dike (1):
virtio_net: Fix recursive call to cpus_read_lock()
Jens Axboe (1):
proc: don't allow async path resolution of /proc/self components
Jesper Dangaard Brouer (1):
netfilter: conntrack: fix reading nf_conntrack_buckets
Jessica Yu (1):
module: delay kobject uevent until after module init call
Jiri Olsa (2):
perf python scripting: Fix printable strings in python3 scripts
perf tools: Add missing swap for ino_generation
Johannes Thumshirn (1):
block: factor out requeue handling from dispatch code
Jonathan Cameron (1):
ACPI: Add out of bounds and numa_off protections to pxm_to_node()
Joseph Qi (1):
ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
Jubin Zhong (1):
PCI: Fix pci_slot_release() NULL pointer dereference
Kaixu Xia (1):
ext4: correctly report "not supported" for {usr, grp}jquota when
!CONFIG_QUOTA
Keqian Zhu (1):
clocksource/drivers/arm_arch_timer: Correct fault programming of
CNTKCTL_EL1.EVNTI
Kirill Tkhai (1):
mm: move nr_deactivate accounting to shrink_active_list()
Lang Dai (1):
uio: free uio id after uio file node is freed
Lecopzer Chen (2):
kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
kasan: fix incorrect arguments passing in kasan_add_zero_shadow
Lee Duncan (1):
scsi: libiscsi: Fix NOP race condition
Lee Jones (1):
Fonts: Replace discarded const qualifier
Leo Yan (1):
perf lock: Don't free "lock_seq_stat" if read_count isn't zero
Leon Romanovsky (1):
net/mlx5: Properly convey driver version to firmware
Lijie (1):
config: enable CONFIG_NVME_MULTIPATH by default
Liu Shixin (3):
config: set default value of CONFIG_TEST_FREE_PAGES
mm: memcontrol: add struct mem_cgroup_extension
mm: fix kabi broken
Lorenzo Pieralisi (1):
asm-generic/io.h: Fix !CONFIG_GENERIC_IOMAP pci_iounmap()
implementation
Lu Jialin (1):
fs: fix files.usage bug when move tasks
Luc Van Oostenryck (1):
xsk: Fix xsk_poll()'s return type
Luo Meng (2):
ext4: fix invalid inode checksum
fail_function: Remove a redundant mutex unlock
Mao Wenan (1):
net: Update window_clamp if SOCK_RCVBUF is set
Marc Zyngier (2):
arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
genirq/irqdomain: Don't try to free an interrupt that has no mapping
Mark Rutland (3):
arm64: syscall: exit userspace before unmasking exceptions
arm64: module: rework special section handling
arm64: module/ftrace: intialize PLT at load time
Martin Wilck (1):
scsi: core: Fix VPD LUN ID designator priorities
Mateusz Nosek (1):
futex: Fix incorrect should_fail_futex() handling
Matteo Croce (4):
Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
reboot: fix overflow parsing reboot cpu number
ipv6: create multicast route with RTPROT_KERNEL
ipv6: set multicast flag on the multicast route
Matthew Wilcox (Oracle) (1):
mm/page_alloc.c: fix freeing non-compound pages
Maurizio Lombardi (2):
scsi: target: remove boilerplate code
scsi: target: fix hang when multiple threads try to destroy the same
iscsi session
Maxim Mikityanskiy (1):
net/tls: Protect from calling tls_dev_del for TLS RX twice
Miaohe Lin (1):
mm/hugetlb: fix potential missing huge page size info
Michael Schaller (1):
efivarfs: Replace invalid slashes with exclamation marks in dentries.
Mike Christie (1):
scsi: target: iscsi: Fix cmd abort fabric stop race
Mike Galbraith (1):
futex: Handle transient "ownerless" rtmutex state correctly
Miklos Szeredi (1):
fuse: fix page dereference after free
Mikulas Patocka (3):
dm integrity: fix the maximum number of arguments
dm integrity: fix flush with external metadata device
dm integrity: fix a crash if "recalculate" used without
"internal_hash"
Ming Lei (2):
scsi: core: Don't start concurrent async scan on same host
block: fix use-after-free in disk_part_iter_next
Minwoo Im (1):
nvme: free sq/cq dbbuf pointers when dbbuf set fails
Miroslav Benes (1):
module: set MODULE_STATE_GOING state when a module fails to load
Moshe Shemesh (2):
net/mlx4_en: Avoid scheduling restart task if it is already running
net/mlx4_en: Handle TX error CQE
Naoya Horiguchi (1):
mm, hwpoison: double-check page count in __get_any_page()
Naveen N. Rao (1):
ftrace: Fix updating FTRACE_FL_TRAMP
Neal Cardwell (1):
tcp: fix cwnd-limited bug for TSO deferral where we send nothing
NeilBrown (1):
NFS: switch nfsiod to be an UNBOUND workqueue.
Nicholas Piggin (1):
mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
Oleg Nesterov (1):
ptrace: fix task_join_group_stop() for the case when current is traced
Oliver Herms (1):
IPv6: Set SIT tunnel hard_header_len to zero
Paul Moore (1):
selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
Paulo Alcantara (1):
cifs: fix potential use-after-free in cifs_echo_request()
Peng Liu (1):
sched/deadline: Fix sched_dl_global_validate()
Peter Zijlstra (2):
serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
perf: Fix get_recursion_context()
Petr Malat (1):
sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian
platforms
Qian Cai (1):
mm/swapfile: do not sleep with a spin lock held
Qiujun Huang (2):
ring-buffer: Return 0 on success from ring_buffer_resize()
tracing: Fix out of bounds write in get_trace_buf
Rafael J. Wysocki (1):
driver core: Extend device_is_dependent()
Randy Dunlap (1):
net: sched: prevent invalid Scell_log shift count
Ritika Srivastava (2):
block: Return blk_status_t instead of errno codes
block: better deal with the delayed not supported case in
blk_cloned_rq_check_limits
Ronnie Sahlberg (1):
cifs: handle -EINTR in cifs_setattr
Ryan Sharpelletti (1):
tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
Sami Tolvanen (1):
arm64: lse: fix LSE atomics with LLVM's integrated assembler
Sean Tranchetti (1):
net: ipv6: fib: flush exceptions when purging route
Shakeel Butt (2):
mm: swap: fix vmstats for huge pages
mm: swap: memcg: fix memcg stats for huge pages
Shijie Luo (1):
mm: mempolicy: fix potential pte_unmap_unlock pte error
Shin'ichiro Kawasaki (1):
uio: Fix use-after-free in uio_unregister_device()
Stefano Brivio (1):
netfilter: ipset: Update byte and packet counters regardless of
whether they match
Steven Rostedt (VMware) (4):
ring-buffer: Fix recursion protection transitions between interrupt
context
ftrace: Fix recursion check for NMI test
ftrace: Handle tracing when switching between context
tracing: Fix userstacktrace option for instances
Subash Abhinov Kasiviswanathan (2):
netfilter: x_tables: Switch synchronization to RCU
netfilter: x_tables: Update remaining dereference to RCU
Sven Eckelmann (2):
vxlan: Add needed_headroom for lower device
vxlan: Copy needed_tailroom from lowerdev
Sylwester Dziedziuch (2):
i40e: Fix removing driver while bare-metal VFs pass traffic
i40e: Fix Error I40E_AQ_RC_EINVAL when removing VFs
Takashi Iwai (1):
libata: transport: Use scnprintf() for avoiding potential buffer
overflow
Tariq Toukan (1):
net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
Thomas Gleixner (12):
sched: Reenable interrupts in do_sched_yield()
futex: Move futex exit handling into futex code
futex: Replace PF_EXITPIDONE with a state
exit/exec: Seperate mm_release()
futex: Split futex_mm_release() for exit/exec
futex: Set task::futex_state to DEAD right after handling futex exit
futex: Mark the begin of futex exit explicitly
futex: Sanitize exit state handling
futex: Provide state handling for exec() as well
futex: Add mutex around futex exit
futex: Provide distinct return value when owner is exiting
futex: Prevent exit livelock
Tianyue Ren (1):
selinux: fix error initialization in inode_doinit_with_dentry()
Trond Myklebust (5):
SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
NFSv4: Fix a pNFS layout related use-after-free race when freeing the
inode
pNFS: Mark layout for return if return-on-close was not sent
NFS/pNFS: Fix a leak of the layout 'plh_outstanding' counter
NFS: nfs_igrab_and_active must first reference the superblock
Tung Nguyen (1):
tipc: fix memory leak caused by tipc_buf_append()
Tyler Hicks (1):
tpm: efi: Don't create binary_bios_measurements file for an empty log
Uwe Kleine-König (1):
spi: fix resource leak for drivers without .remove callback
Vadim Fedorenko (1):
net/tls: missing received data after fast remote close
Valentin Schneider (1):
arm64: topology: Stop using MPIDR for topology information
Vamshi K Sthambamkadi (1):
efivarfs: fix memory leak in efivarfs_create()
Vasily Averin (2):
netfilter: ipset: fix shift-out-of-bounds in htable_bits()
net: drop bogus skb with CHECKSUM_PARTIAL and offset beyond end of
trimmed packet
Vincenzo Frascino (1):
arm64: lse: Fix LSE atomics with LLVM
Vladyslav Tarasiuk (1):
net/mlx5: Disable QoS when min_rates on all VFs are zero
Wang Hai (4):
devlink: Add missing genlmsg_cancel() in
devlink_nl_sb_port_pool_fill()
inet_diag: Fix error path to cancel the meseage in
inet_req_diag_fill()
tipc: fix memory leak in tipc_topsrv_start()
ipv6: addrlabel: fix possible memory leak in ip6addrlbl_net_init
Wang Wensheng (1):
sbsa_gwdt: Add WDIOF_PRETIMEOUT flag to watchdog_info at defination
Wei Li (1):
irqchip/gic-v3: Fix compiling error on ARM32 with GICv3
Wei Yang (1):
mm: thp: don't need care deferred split queue in memcg charge move
path
Weilong Chen (1):
hugetlbfs: Add dependency with ascend memory features
Wengang Wang (1):
ocfs2: initialize ip_next_orphan
Will Deacon (3):
arm64: psci: Avoid printing in cpu_psci_cpu_die()
arm64: pgtable: Fix pte_accessible()
arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
Willem de Bruijn (1):
sock: set sk_err to ee_errno on dequeue from errq
Wu Bo (1):
scsi: libiscsi: fix task hung when iscsid deamon exited
Xie XiuQi (1):
cputime: fix undefined reference to get_idle_time when CONFIG_PROC_FS
disabled
Xin Long (1):
sctp: change to hold/put transport for proto_unreach_timer
Xiongfeng Wang (1):
arm64: fix compile error when CONFIG_HOTPLUG_CPU is disabled
Xiubo Li (1):
nbd: make the config put is called before the notifying the waiter
Xu Qiang (4):
NMI: Enable arm-pmu interrupt as NMI in Acensed.
irqchip/gic-v3-its: Unconditionally save/restore the ITS state on
suspend.
irqchip/irq-gic-v3: Add workaround bindings in device tree to init ts
core GICR.
Document: In the binding document, add enable-init-all-GICR field
description.
Yang Shi (6):
mm: list_lru: set shrinker map bit when child nr_items is not zero
mm: thp: extract split_queue_* into a struct
mm: move mem_cgroup_uncharge out of __page_cache_release()
mm: shrinker: make shrinker not depend on memcg kmem
mm: thp: make deferred split shrinker memcg aware
mm: vmscan: protect shrinker idr replace with CONFIG_MEMCG
Yang Yingliang (5):
arm64: arch_timer: only do cntvct workaround on VDSO path on D05
armv7 fix compile error
Kconfig: disable KTASK by default
futex: sched: fix kabi broken in task_struct
futex: sched: fix UAF when free futex_exit_mutex in free_task()
Yi-Hung Wei (1):
ip_tunnels: Set tunnel option flag when tunnel metadata is present
Yicong Yang (1):
libfs: fix error cast of negative value in simple_attr_write()
Yu Kuai (2):
blk-cgroup: prevent rcu_sched detected stalls warnings in
blkg_destroy_all()
blk-throttle: don't check whether or not lower limit is valid if
CONFIG_BLK_DEV_THROTTLING_LOW is off
Yufen Yu (2):
bdi: fix compiler error in bdi_get_dev_name()
scsi: do quiesce for enclosure driver
Yunfeng Ye (1):
workqueue: Kick a worker based on the actual activation of delayed
works
Yunjian Wang (2):
net: hns: fix return value check in __lb_other_process()
vhost_net: fix ubuf refcount incorrectly when sendmsg fails
Yunsheng Lin (1):
net: sch_generic: fix the missing new qdisc assignment bug
Zeng Tao (1):
time: Prevent undefined behaviour in timespec64_to_ns()
Zhang Changzhong (2):
ah6: fix error return code in ah6_input()
net: bridge: vlan: fix error return code in __vlan_add()
Zhao Heming (2):
md/cluster: block reshape with remote resync job
md/cluster: fix deadlock when node is doing resync job
Zhengyuan Liu (3):
arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
hifc: remove unnecessary __init specifier
mmap: fix a compiling error for 'MAP_PA32BIT'
Zhou Guanghui (2):
memcg/ascend: Check sysctl oom config for memcg oom
memcg/ascend: enable kmem cgroup by default for ascend
Zqiang (1):
kthread_worker: prevent queuing delayed work from timer_fn when it is
being canceled
chenmaodong (1):
fix virtio_gpu use-after-free while creating dumb
j.nixdorf(a)avm.de (1):
net: sunrpc: interpret the return value of kstrtou32 correctly
lijinlin (1):
ext4: add ext3 report error to userspace by netlink
miaoyubo (1):
KVM: Enable PUD huge mappings only on 1620
yangerkun (1):
ext4: fix bug for rename with RENAME_WHITEOUT
zhuoliang zhang (1):
net: xfrm: fix a race condition during allocing spi
.../interrupt-controller/arm,gic-v3.txt | 4 +
Documentation/networking/bonding.txt | 16 +-
arch/Kconfig | 7 +
arch/alpha/include/uapi/asm/mman.h | 2 +
arch/arm/kernel/perf_event_v7.c | 16 +-
arch/arm64/Kconfig | 2 +
arch/arm64/configs/euleros_defconfig | 1 +
arch/arm64/configs/hulk_defconfig | 1 +
arch/arm64/configs/openeuler_defconfig | 3 +-
arch/arm64/include/asm/atomic_lse.h | 76 ++-
arch/arm64/include/asm/cpufeature.h | 4 +
arch/arm64/include/asm/lse.h | 6 +-
arch/arm64/include/asm/memory.h | 11 +
arch/arm64/include/asm/numa.h | 3 +
arch/arm64/include/asm/pgtable.h | 34 +-
arch/arm64/kernel/cpu_errata.c | 8 +
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/ftrace.c | 50 +-
arch/arm64/kernel/module.c | 47 +-
arch/arm64/kernel/psci.c | 5 +-
arch/arm64/kernel/setup.c | 5 +-
arch/arm64/kernel/syscall.c | 2 +-
arch/arm64/kernel/topology.c | 43 +-
arch/arm64/lib/memcpy.S | 3 +-
arch/arm64/lib/memmove.S | 3 +-
arch/arm64/lib/memset.S | 3 +-
arch/arm64/mm/init.c | 17 +-
arch/arm64/mm/numa.c | 6 +-
arch/mips/include/uapi/asm/mman.h | 2 +
arch/parisc/include/uapi/asm/mman.h | 2 +
arch/powerpc/include/asm/uaccess.h | 4 +-
arch/powerpc/include/uapi/asm/mman.h | 2 +
arch/sparc/include/uapi/asm/mman.h | 2 +
arch/x86/configs/hulk_defconfig | 1 +
arch/x86/configs/openeuler_defconfig | 1 +
arch/xtensa/include/uapi/asm/mman.h | 2 +
block/bfq-iosched.c | 8 +-
block/blk-cgroup.c | 30 +-
block/blk-core.c | 39 +-
block/blk-mq.c | 29 +-
block/blk-throttle.c | 6 +
block/genhd.c | 9 +-
drivers/acpi/acpi_pnp.c | 3 +
drivers/acpi/internal.h | 2 +-
drivers/acpi/numa.c | 2 +-
drivers/acpi/resource.c | 2 +-
drivers/acpi/scan.c | 17 +-
drivers/ata/libata-transport.c | 10 +-
drivers/base/core.c | 21 +-
drivers/block/nbd.c | 3 +-
drivers/block/null_blk_zoned.c | 20 +-
drivers/char/Kconfig | 2 +-
drivers/char/random.c | 1 -
drivers/char/tpm/eventlog/efi.c | 5 +
drivers/clocksource/arm_arch_timer.c | 36 +-
drivers/firmware/efi/efi.c | 4 -
drivers/firmware/efi/libstub/arm-stub.c | 3 -
drivers/gpu/drm/virtio/virtgpu_gem.c | 4 +-
drivers/irqchip/irq-gic-v3-its.c | 30 +-
drivers/irqchip/irq-gic-v3.c | 18 +-
drivers/md/dm-bufio.c | 6 +
drivers/md/dm-integrity.c | 58 ++-
drivers/md/dm-snap.c | 24 +
drivers/md/dm-table.c | 15 +-
drivers/md/dm-verity-target.c | 12 +-
drivers/md/md-cluster.c | 67 +--
drivers/md/md.c | 14 +-
drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c | 4 +-
drivers/net/bonding/bond_main.c | 92 ++--
drivers/net/bonding/bond_netlink.c | 14 +
drivers/net/bonding/bond_options.c | 71 ++-
drivers/net/bonding/bond_procfs.c | 2 +
drivers/net/bonding/bond_sysfs.c | 13 +
drivers/net/bonding/bond_sysfs_slave.c | 18 +-
.../net/ethernet/hisilicon/hns/hns_ethtool.c | 4 +
drivers/net/ethernet/intel/i40e/i40e.h | 4 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 32 +-
.../ethernet/intel/i40e/i40e_virtchnl_pf.c | 30 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 24 +-
.../net/ethernet/mellanox/mlx4/en_netdev.c | 21 +-
drivers/net/ethernet/mellanox/mlx4/en_tx.c | 40 +-
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 12 +-
.../net/ethernet/mellanox/mlx5/core/en_fs.c | 3 +
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 15 +-
.../net/ethernet/mellanox/mlx5/core/main.c | 6 +-
.../ethernet/mellanox/mlx5/core/pagealloc.c | 21 +-
drivers/net/ethernet/mellanox/mlxsw/core.c | 8 +-
drivers/net/geneve.c | 3 +-
drivers/net/macvlan.c | 5 +-
drivers/net/virtio_net.c | 12 +-
drivers/net/vxlan.c | 3 +
drivers/nvme/host/pci.c | 15 +
drivers/pci/controller/pcie-iproc.c | 10 +-
drivers/pci/pci.c | 14 +-
drivers/pci/slot.c | 6 +-
drivers/scsi/huawei/hifc/unf_common.h | 2 +-
drivers/scsi/huawei/hifc/unf_scsi.c | 23 +
drivers/scsi/libiscsi.c | 33 +-
drivers/scsi/scsi_lib.c | 126 +++--
drivers/scsi/scsi_scan.c | 11 +-
drivers/scsi/scsi_transport_spi.c | 27 +-
drivers/spi/spi.c | 19 +-
drivers/target/iscsi/iscsi_target.c | 96 ++--
drivers/target/iscsi/iscsi_target.h | 1 -
drivers/target/iscsi/iscsi_target_configfs.c | 5 +-
drivers/target/iscsi/iscsi_target_login.c | 5 +-
drivers/tty/serial/amba-pl011.c | 11 +-
drivers/tty/serial/serial_core.c | 4 +
drivers/uio/uio.c | 12 +-
drivers/vfio/pci/vfio_pci.c | 3 +-
drivers/vhost/net.c | 6 +-
drivers/watchdog/sbsa_gwdt.c | 6 +-
fs/cifs/cifs_unicode.c | 8 +-
fs/cifs/connect.c | 2 +
fs/cifs/inode.c | 13 +-
fs/efivarfs/inode.c | 2 +
fs/efivarfs/super.c | 3 +
fs/exec.c | 17 +-
fs/ext4/ext4.h | 6 +-
fs/ext4/ext4_jbd2.c | 1 -
fs/ext4/file.c | 1 +
fs/ext4/inline.c | 1 +
fs/ext4/inode.c | 31 +-
fs/ext4/ioctl.c | 3 +
fs/ext4/mballoc.c | 1 +
fs/ext4/namei.c | 23 +-
fs/ext4/resize.c | 8 +-
fs/ext4/super.c | 32 +-
fs/ext4/xattr.c | 1 +
fs/fcntl.c | 10 +-
fs/filescontrol.c | 73 +--
fs/fuse/dev.c | 28 +-
fs/hugetlbfs/inode.c | 2 +-
fs/libfs.c | 6 +-
fs/lockd/host.c | 20 +-
fs/nfs/inode.c | 2 +-
fs/nfs/internal.h | 12 +-
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/nfs4super.c | 2 +-
fs/nfs/pnfs.c | 40 +-
fs/nfs/pnfs.h | 5 +
fs/nfs_common/grace.c | 6 +-
fs/ocfs2/super.c | 1 +
fs/proc/generic.c | 55 ++-
fs/proc/internal.h | 7 +
fs/proc/proc_net.c | 16 -
fs/proc/self.c | 7 +
fs/quota/quota_tree.c | 8 +-
fs/super.c | 33 +-
fs/xfs/libxfs/xfs_alloc.c | 1 +
fs/xfs/libxfs/xfs_bmap.c | 19 +-
fs/xfs/libxfs/xfs_bmap.h | 2 +-
fs/xfs/libxfs/xfs_rmap.c | 2 +-
fs/xfs/scrub/bmap.c | 10 +-
fs/xfs/scrub/btree.c | 45 +-
fs/xfs/scrub/inode.c | 3 +-
fs/xfs/scrub/refcount.c | 8 +-
fs/xfs/xfs_iops.c | 10 +
fs/xfs/xfs_pnfs.c | 2 +-
fs/xfs/xfs_rtalloc.c | 10 +-
include/asm-generic/io.h | 39 +-
include/linux/backing-dev.h | 1 +
include/linux/blkdev.h | 1 +
include/linux/compat.h | 2 -
include/linux/dm-bufio.h | 1 +
include/linux/efi.h | 7 -
include/linux/futex.h | 39 +-
include/linux/huge_mm.h | 9 +
include/linux/hugetlb.h | 10 +-
include/linux/if_team.h | 5 +-
include/linux/memblock.h | 3 -
include/linux/memcontrol.h | 32 +-
include/linux/mm.h | 2 +
include/linux/mm_types.h | 1 +
include/linux/mman.h | 15 +
include/linux/mmzone.h | 8 +
include/linux/netfilter/x_tables.h | 5 +-
include/linux/netfilter_ipv4.h | 2 +-
include/linux/netfilter_ipv6.h | 2 +-
include/linux/netpoll.h | 10 +-
include/linux/prandom.h | 36 +-
include/linux/proc_fs.h | 8 +-
include/linux/sched.h | 5 +-
include/linux/sched/cputime.h | 5 +
include/linux/sched/mm.h | 6 +-
include/linux/shrinker.h | 7 +-
include/linux/skbuff.h | 5 +
include/linux/sunrpc/xprt.h | 1 +
include/linux/time64.h | 4 +
include/net/bond_options.h | 1 +
include/net/bonding.h | 14 +-
include/net/ip_tunnels.h | 7 +-
include/net/red.h | 4 +-
include/net/tls.h | 6 +
include/scsi/libiscsi.h | 3 +
include/target/iscsi/iscsi_target_core.h | 2 +-
include/uapi/asm-generic/mman.h | 1 +
include/uapi/linux/if_link.h | 1 +
init/Kconfig | 2 +-
kernel/events/internal.h | 2 +-
kernel/exit.c | 35 +-
kernel/fail_function.c | 5 +-
kernel/fork.c | 61 ++-
kernel/futex.c | 291 +++++++++--
kernel/irq/irqdomain.c | 11 +-
kernel/kthread.c | 3 +-
kernel/module.c | 6 +-
kernel/reboot.c | 28 +-
kernel/sched/core.c | 6 +-
kernel/sched/cputime.c | 6 +
kernel/sched/deadline.c | 5 +-
kernel/sched/sched.h | 42 +-
kernel/signal.c | 19 +-
kernel/time/itimer.c | 4 -
kernel/time/tick-common.c | 2 +
kernel/time/timer.c | 7 -
kernel/trace/ftrace.c | 22 +-
kernel/trace/ring_buffer.c | 66 ++-
kernel/trace/trace.c | 9 +-
kernel/trace/trace.h | 32 +-
kernel/trace/trace_selftest.c | 9 +-
kernel/workqueue.c | 13 +-
lib/Kconfig.debug | 9 +
lib/Makefile | 1 +
lib/fonts/font_10x18.c | 2 +-
lib/fonts/font_6x10.c | 2 +-
lib/fonts/font_6x11.c | 2 +-
lib/fonts/font_7x14.c | 2 +-
lib/fonts/font_8x16.c | 2 +-
lib/fonts/font_8x8.c | 2 +-
lib/fonts/font_acorn_8x8.c | 2 +-
lib/fonts/font_mini_4x6.c | 2 +-
lib/fonts/font_pearl_8x8.c | 2 +-
lib/fonts/font_sun12x22.c | 2 +-
lib/fonts/font_sun8x16.c | 2 +-
lib/genalloc.c | 25 +-
lib/random32.c | 462 +++++++++++-------
lib/scatterlist.c | 2 +-
lib/test_free_pages.c | 42 ++
mm/huge_memory.c | 167 +++++--
mm/hugetlb.c | 5 +-
mm/kasan/kasan_init.c | 23 +-
mm/list_lru.c | 10 +-
mm/memblock.c | 11 +-
mm/memcontrol.c | 34 +-
mm/memory-failure.c | 6 +
mm/mempolicy.c | 6 +-
mm/mlock.c | 25 +-
mm/mmap.c | 27 +-
mm/page_alloc.c | 9 +
mm/slub.c | 2 +-
mm/swap.c | 37 +-
mm/swapfile.c | 4 +-
mm/vmscan.c | 64 +--
net/8021q/vlan.c | 3 +-
net/8021q/vlan_dev.c | 5 +-
net/bridge/br_device.c | 1 +
net/bridge/br_netfilter_hooks.c | 7 +-
net/bridge/br_private.h | 5 +-
net/bridge/br_vlan.c | 4 +-
net/ceph/messenger.c | 5 +
net/core/dev.c | 5 +
net/core/devlink.c | 6 +-
net/core/lwt_bpf.c | 8 +-
net/core/net-sysfs.c | 65 ++-
net/core/netpoll.c | 51 +-
net/core/skbuff.c | 23 +-
net/dsa/slave.c | 5 +-
net/ipv4/fib_frontend.c | 2 +-
net/ipv4/gre_demux.c | 2 +-
net/ipv4/inet_diag.c | 4 +-
net/ipv4/ip_output.c | 2 +-
net/ipv4/ip_tunnel.c | 10 +-
net/ipv4/netfilter.c | 12 +-
net/ipv4/netfilter/arp_tables.c | 16 +-
net/ipv4/netfilter/ip_tables.c | 16 +-
net/ipv4/netfilter/ipt_SYNPROXY.c | 2 +-
net/ipv4/netfilter/ipt_rpfilter.c | 2 +-
net/ipv4/netfilter/iptable_mangle.c | 2 +-
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 2 +-
net/ipv4/netfilter/nf_reject_ipv4.c | 2 +-
net/ipv4/netfilter/nft_chain_route_ipv4.c | 2 +-
net/ipv4/route.c | 7 +-
net/ipv4/syncookies.c | 9 +-
net/ipv4/tcp.c | 2 +
net/ipv4/tcp_bbr.c | 2 +-
net/ipv4/tcp_cong.c | 5 +
net/ipv4/tcp_input.c | 6 +-
net/ipv4/tcp_output.c | 9 +-
net/ipv4/udp.c | 3 +-
net/ipv6/addrconf.c | 3 +-
net/ipv6/addrlabel.c | 26 +-
net/ipv6/ah6.c | 3 +-
net/ipv6/ip6_fib.c | 5 +-
net/ipv6/ip6_gre.c | 16 +-
net/ipv6/ip6_output.c | 40 +-
net/ipv6/netfilter.c | 6 +-
net/ipv6/netfilter/ip6_tables.c | 16 +-
net/ipv6/netfilter/ip6table_mangle.c | 2 +-
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 2 +-
net/ipv6/netfilter/nft_chain_route_ipv6.c | 2 +-
net/ipv6/sit.c | 2 -
net/ipv6/syncookies.c | 10 +-
net/netfilter/ipset/ip_set_core.c | 3 +-
net/netfilter/ipset/ip_set_hash_gen.h | 20 +-
net/netfilter/ipvs/ip_vs_core.c | 4 +-
net/netfilter/nf_conntrack_standalone.c | 3 +
net/netfilter/nf_nat_core.c | 1 +
net/netfilter/nf_tables_api.c | 3 +-
net/netfilter/x_tables.c | 49 +-
net/netfilter/xt_RATEEST.c | 3 +
net/sched/cls_tcindex.c | 8 +-
net/sched/sch_api.c | 3 +-
net/sched/sch_choke.c | 2 +-
net/sched/sch_generic.c | 3 +
net/sched/sch_gred.c | 2 +-
net/sched/sch_netem.c | 9 +-
net/sched/sch_red.c | 2 +-
net/sched/sch_sfq.c | 2 +-
net/sctp/input.c | 4 +-
net/sctp/sm_sideeffect.c | 8 +-
net/sctp/transport.c | 2 +-
net/sunrpc/addr.c | 2 +-
net/sunrpc/xprt.c | 65 ++-
net/sunrpc/xprtrdma/module.c | 1 +
net/sunrpc/xprtrdma/transport.c | 1 +
net/sunrpc/xprtsock.c | 4 +
net/tipc/link.c | 9 +-
net/tipc/msg.c | 5 +-
net/tipc/topsrv.c | 10 +-
net/tls/tls_device.c | 5 +-
net/tls/tls_sw.c | 6 +
net/xdp/xsk.c | 8 +-
net/xfrm/xfrm_state.c | 8 +-
security/lsm_audit.c | 7 +-
security/selinux/hooks.c | 16 +-
security/selinux/ibpkey.c | 4 +-
sound/soc/codecs/Kconfig | 1 +
tools/include/uapi/linux/if_link.h | 1 +
tools/perf/builtin-lock.c | 2 +-
tools/perf/util/print_binary.c | 2 +-
.../scripting-engines/trace-event-python.c | 7 +-
tools/perf/util/session.c | 1 +
virt/kvm/arm/mmu.c | 7 +
344 files changed, 3424 insertions(+), 1701 deletions(-)
create mode 100644 lib/test_free_pages.c
--
2.25.1
1
316
[PATCH 001/316] blk-cgroup: prevent rcu_sched detected stalls warnings in blkg_destroy_all()
by Cheng Jian 22 Feb '21
by Cheng Jian 22 Feb '21
22 Feb '21
From: Yu Kuai <yukuai3(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 46357
CVE: NA
---------------------------
test procedures:
a. create 20000 cgroups, and echo "8:0 10000" to
blkio.throttle.write_bps_device
b. echo 1 > /sys/blocd/sda/device/delete
test result:
rcu: INFO: rcu_sched detected stalls on CPUs/tasks: [5/1143]
rcu: 0-...0: (0 ticks this GP) idle=0f2/1/0x4000000000000000 softirq=15507/15507 fq
rcu: (detected by 6, t=60012 jiffies, g=119977, q=27153)
NMI backtrace for cpu 0
CPU: 0 PID: 443 Comm: bash Not tainted 4.19.95-00061-g0bcc83b30eec #63
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-p4
RIP: 0010:blk_throtl_update_limit_valid.isra.0+0x116/0x2a0
Code: 01 00 00 e8 7c dd 74 ff 48 83 bb 78 01 00 00 00 0f 85 54 01 00 00 48 8d bb 88 01 1
RSP: 0018:ffff8881030bf9f0 EFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff8880b4f37080 RCX: ffffffff95da0afe
RDX: dffffc0000000000 RSI: ffff888100373980 RDI: ffff8880b4f37208
RBP: ffff888100deca00 R08: ffffffff9528f951 R09: 0000000000000001
R10: ffffed10159dbf56 R11: ffff8880acedfab3 R12: ffff8880b9fda498
R13: ffff8880b9fda4f4 R14: 0000000000000050 R15: ffffffff98b622c0
FS: 00007feb51c51700(0000) GS:ffff888106200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000561619547080 CR3: 0000000102bc9000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
throtl_pd_offline+0x98/0x100
blkg_destroy+0x133/0x630
? blkcg_deactivate_policy+0x2c0/0x2c0
? lock_timer_base+0x65/0x110
blkg_destroy_all+0x7f/0x100
blkcg_exit_queue+0x3f/0xa5
blk_exit_queue+0x69/0xa0
blk_cleanup_queue+0x226/0x360
__scsi_remove_device+0xb4/0x3c0
scsi_remove_device+0x38/0x60
sdev_store_delete+0x74/0x100
? dev_driver_string+0xb0/0xb0
dev_attr_store+0x41/0x70
sysfs_kf_write+0x89/0xc0
kernfs_fop_write+0x1b6/0x2e0
? sysfs_kf_bin_read+0x130/0x130
__vfs_write+0xca/0x420
? kernel_read+0xc0/0xc0
? __alloc_fd+0x16f/0x2d0
? __fd_install+0x95/0x1a0
? handle_mm_fault+0x3e0/0x560
vfs_write+0x11a/0x2f0
ksys_write+0xb9/0x1e0
? __x64_sys_read+0x60/0x60
? kasan_check_write+0x20/0x30
? filp_close+0xb5/0xf0
__x64_sys_write+0x46/0x60
do_syscall_64+0xd9/0x1f0
entry_SYSCALL_64_after_hwframe+0x44/0xa9
The usage of so many blkg is very rare, however, such problem do exist
in theory. In order to avoid such warnings, release 'q->queue_lock' for
a while when a batch of blkg were destroyed.
Signed-off-by: Yu Kuai <yukuai3(a)huawei.com>
Reviewed-by: Tao Hou <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
block/blk-cgroup.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e592167449aa..c64f0afa27dc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -364,16 +364,31 @@ static void blkg_destroy(struct blkcg_gq *blkg)
*/
static void blkg_destroy_all(struct request_queue *q)
{
+#define BLKG_DESTROY_BATCH 4096
struct blkcg_gq *blkg, *n;
+ int count;
lockdep_assert_held(q->queue_lock);
+again:
+ count = BLKG_DESTROY_BATCH;
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
struct blkcg *blkcg = blkg->blkcg;
spin_lock(&blkcg->lock);
blkg_destroy(blkg);
spin_unlock(&blkcg->lock);
+ /*
+ * If the list is too long, the loop can took a long time,
+ * thus relese the lock for a while when a batch of blkg
+ * were destroyed.
+ */
+ if (!--count) {
+ spin_unlock_irq(q->queue_lock);
+ cond_resched();
+ spin_lock_irq(q->queue_lock);
+ goto again;
+ }
}
q->root_blkg = NULL;
--
2.25.1
1
13
[PATCH 001/316] blk-cgroup: prevent rcu_sched detected stalls warnings in blkg_destroy_all()
by Cheng Jian 22 Feb '21
by Cheng Jian 22 Feb '21
22 Feb '21
From: Yu Kuai <yukuai3(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 46357
CVE: NA
---------------------------
test procedures:
a. create 20000 cgroups, and echo "8:0 10000" to
blkio.throttle.write_bps_device
b. echo 1 > /sys/blocd/sda/device/delete
test result:
rcu: INFO: rcu_sched detected stalls on CPUs/tasks: [5/1143]
rcu: 0-...0: (0 ticks this GP) idle=0f2/1/0x4000000000000000 softirq=15507/15507 fq
rcu: (detected by 6, t=60012 jiffies, g=119977, q=27153)
NMI backtrace for cpu 0
CPU: 0 PID: 443 Comm: bash Not tainted 4.19.95-00061-g0bcc83b30eec #63
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-p4
RIP: 0010:blk_throtl_update_limit_valid.isra.0+0x116/0x2a0
Code: 01 00 00 e8 7c dd 74 ff 48 83 bb 78 01 00 00 00 0f 85 54 01 00 00 48 8d bb 88 01 1
RSP: 0018:ffff8881030bf9f0 EFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff8880b4f37080 RCX: ffffffff95da0afe
RDX: dffffc0000000000 RSI: ffff888100373980 RDI: ffff8880b4f37208
RBP: ffff888100deca00 R08: ffffffff9528f951 R09: 0000000000000001
R10: ffffed10159dbf56 R11: ffff8880acedfab3 R12: ffff8880b9fda498
R13: ffff8880b9fda4f4 R14: 0000000000000050 R15: ffffffff98b622c0
FS: 00007feb51c51700(0000) GS:ffff888106200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000561619547080 CR3: 0000000102bc9000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
throtl_pd_offline+0x98/0x100
blkg_destroy+0x133/0x630
? blkcg_deactivate_policy+0x2c0/0x2c0
? lock_timer_base+0x65/0x110
blkg_destroy_all+0x7f/0x100
blkcg_exit_queue+0x3f/0xa5
blk_exit_queue+0x69/0xa0
blk_cleanup_queue+0x226/0x360
__scsi_remove_device+0xb4/0x3c0
scsi_remove_device+0x38/0x60
sdev_store_delete+0x74/0x100
? dev_driver_string+0xb0/0xb0
dev_attr_store+0x41/0x70
sysfs_kf_write+0x89/0xc0
kernfs_fop_write+0x1b6/0x2e0
? sysfs_kf_bin_read+0x130/0x130
__vfs_write+0xca/0x420
? kernel_read+0xc0/0xc0
? __alloc_fd+0x16f/0x2d0
? __fd_install+0x95/0x1a0
? handle_mm_fault+0x3e0/0x560
vfs_write+0x11a/0x2f0
ksys_write+0xb9/0x1e0
? __x64_sys_read+0x60/0x60
? kasan_check_write+0x20/0x30
? filp_close+0xb5/0xf0
__x64_sys_write+0x46/0x60
do_syscall_64+0xd9/0x1f0
entry_SYSCALL_64_after_hwframe+0x44/0xa9
The usage of so many blkg is very rare, however, such problem do exist
in theory. In order to avoid such warnings, release 'q->queue_lock' for
a while when a batch of blkg were destroyed.
Signed-off-by: Yu Kuai <yukuai3(a)huawei.com>
Reviewed-by: Tao Hou <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
block/blk-cgroup.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e592167449aa..c64f0afa27dc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -364,16 +364,31 @@ static void blkg_destroy(struct blkcg_gq *blkg)
*/
static void blkg_destroy_all(struct request_queue *q)
{
+#define BLKG_DESTROY_BATCH 4096
struct blkcg_gq *blkg, *n;
+ int count;
lockdep_assert_held(q->queue_lock);
+again:
+ count = BLKG_DESTROY_BATCH;
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
struct blkcg *blkcg = blkg->blkcg;
spin_lock(&blkcg->lock);
blkg_destroy(blkg);
spin_unlock(&blkcg->lock);
+ /*
+ * If the list is too long, the loop can took a long time,
+ * thus relese the lock for a while when a batch of blkg
+ * were destroyed.
+ */
+ if (!--count) {
+ spin_unlock_irq(q->queue_lock);
+ cond_resched();
+ spin_lock_irq(q->queue_lock);
+ goto again;
+ }
}
q->root_blkg = NULL;
--
2.25.1
1
4
2
1
申报议题:
2. 讨论设立sig安全联络员及如何缩短sig所属项目的CVE响应时间
魏刚
---Original---
From: "openEuler conference"<public(a)openeuler.io>
Date: Thu, Feb 18, 2021 17:12 PM
To: "dev"<dev(a)openeuler.org>;"kernel"<kernel(a)openeuler.org>;
Subject: [Dev] openEuler kernel sig meeting
您好!
openEuler Kernel SIG 邀请您参加 2021-02-19 10:00 召开的ZOOM会议
会议主题:openEuler kernel sig meeting
会议内容:1. 树莓派补丁合入openEuler 5.10 内核讨论
会议链接:https://zoom.us/j/92887086207?pwd=emdmSVVFekh5eXRSczNNTngrcWYzUT09
更多资讯尽在:https://openeuler.org/zh/
Hello!
openEuler Kernel SIG invites you to attend the ZOOM conference will be held at 2021-02-19 10:00,
The subject of the conference is openEuler kernel sig meeting,
Summary: 1. 树莓派补丁合入openEuler 5.10 内核讨论
You can join the meeting at https://zoom.us/j/92887086207?pwd=emdmSVVFekh5eXRSczNNTngrcWYzUT09.
More information
1
0
Arnold Gozum (1):
platform/x86: intel-vbtn: Support for tablet mode on Dell Inspiron
7352
Brian King (1):
scsi: ibmvfc: Set default timeout to avoid crash during migration
Christian Brauner (1):
sysctl: handle overflow in proc_get_long
Eric Dumazet (1):
net_sched: gen_estimator: support large ewma log
Felix Fietkau (1):
mac80211: fix fast-rx encryption check
Greg Kroah-Hartman (1):
Linux 4.19.174
Hans de Goede (1):
platform/x86: touchscreen_dmi: Add swap-x-y quirk for Goodix
touchscreen on Estar Beauty HD tablet
Javed Hasan (1):
scsi: libfc: Avoid invoking response handler twice if ep is already
completed
Josh Poimboeuf (1):
objtool: Don't fail on missing symbol table
Lijun Pan (1):
ibmvnic: Ensure that CRQ entry read are correctly ordered
Martin Wilck (1):
scsi: scsi_transport_srp: Don't block target in failfast state
Michael Ellerman (1):
selftests/powerpc: Only test lwm/stmw on big endian
Pan Bian (1):
net: dsa: bcm_sf2: put device node before return
Peter Zijlstra (3):
x86: __always_inline __{rd,wr}msr()
kthread: Extract KTHREAD_IS_PER_CPU
workqueue: Restrict affinity change to rescuer
Rafael J. Wysocki (1):
ACPI: thermal: Do not call acpi_thermal_check() directly
Tony Lindgren (1):
phy: cpcap-usb: Fix warning for missing regulator_disable
Makefile | 2 +-
arch/x86/include/asm/msr.h | 4 +-
drivers/acpi/thermal.c | 55 +++++++++++++------
drivers/net/dsa/bcm_sf2.c | 8 ++-
drivers/net/ethernet/ibm/ibmvnic.c | 6 ++
drivers/phy/motorola/phy-cpcap-usb.c | 19 +++++--
drivers/platform/x86/intel-vbtn.c | 6 ++
drivers/platform/x86/touchscreen_dmi.c | 18 ++++++
drivers/scsi/ibmvscsi/ibmvfc.c | 4 +-
drivers/scsi/libfc/fc_exch.c | 16 +++++-
drivers/scsi/scsi_transport_srp.c | 9 ++-
include/linux/kthread.h | 3 +
kernel/kthread.c | 27 ++++++++-
kernel/smpboot.c | 1 +
kernel/sysctl.c | 2 +
kernel/workqueue.c | 9 +--
net/core/gen_estimator.c | 11 ++--
net/mac80211/rx.c | 2 +
tools/objtool/elf.c | 7 ++-
.../powerpc/alignment/alignment_handler.c | 5 +-
20 files changed, 168 insertions(+), 46 deletions(-)
--
2.25.1
1
18
[PATCH kernel-4.19 1/3] mmap: fix a compiling error for 'MAP_CHECKNODE'
by Yang Yingliang 09 Feb '21
by Yang Yingliang 09 Feb '21
09 Feb '21
From: Bixuan Cui <cuibixuan(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
MAP_CHECKNODE was defined in uapi/asm-generic/mman.h, that was not
automatically included by mm/mmap.c when building on platforms such as
mips, and result in following compiling error:
mm/mmap.c: In function ‘__do_mmap’:
mm/mmap.c:1581:14: error: ‘MAP_CHECKNODE’ undeclared (first use in this function)
if (flags & MAP_CHECKNODE)
^
mm/mmap.c:1581:14: note: each undeclared identifier is reported only once for each function it appears in
scripts/Makefile.build:303: recipe for target 'mm/mmap.o' failed
Fixes: 56a22a261008 ("arm64/ascend: mm: Add MAP_CHECKNODE flag to check node hugetlb")
Signed-off-by: Bixuan Cui <cuibixuan(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/alpha/include/uapi/asm/mman.h | 1 +
arch/mips/include/uapi/asm/mman.h | 1 +
arch/parisc/include/uapi/asm/mman.h | 1 +
arch/powerpc/include/uapi/asm/mman.h | 1 +
arch/sparc/include/uapi/asm/mman.h | 1 +
arch/xtensa/include/uapi/asm/mman.h | 1 +
6 files changed, 6 insertions(+)
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index b3acfc00c8ec5..1c7ce2716ad37 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -34,6 +34,7 @@
#define MAP_HUGETLB 0x100000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x200000/* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_SYNC 2 /* synchronous memory sync */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 72a00c746e781..4570a54ac1d90 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -52,6 +52,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
/*
* Flags for msync
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 9e989d649e854..06857eb1bee8f 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -28,6 +28,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#define MS_SYNC 1 /* synchronous memory sync */
#define MS_ASYNC 2 /* sync memory asynchronously */
diff --git a/arch/powerpc/include/uapi/asm/mman.h b/arch/powerpc/include/uapi/asm/mman.h
index 95f884ada96f1..24354f792b00d 100644
--- a/arch/powerpc/include/uapi/asm/mman.h
+++ b/arch/powerpc/include/uapi/asm/mman.h
@@ -30,6 +30,7 @@
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
/* Override any generic PKEY permission defines */
#define PKEY_DISABLE_EXECUTE 0x4
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
index 0d1881b8f30d1..214abe17f44a0 100644
--- a/arch/sparc/include/uapi/asm/mman.h
+++ b/arch/sparc/include/uapi/asm/mman.h
@@ -27,6 +27,7 @@
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#endif /* _UAPI__SPARC_MMAN_H__ */
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index f584a590bb001..2c9d705602382 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -59,6 +59,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
* uninitialized */
--
2.25.1
1
2
Andrea Righi (1):
leds: trigger: fix potential deadlock with libata
Baoquan He (1):
kernel: kexec: remove the lock operation of system_transition_mutex
Bartosz Golaszewski (1):
iommu/vt-d: Don't dereference iommu_device if IOMMU_API is not built
Claudiu Beznea (1):
drivers: soc: atmel: add null entry at the end of
at91_soc_allowed_list[]
Dan Carpenter (1):
can: dev: prevent potential information leak in can_fill_info()
David Woodhouse (2):
xen: Fix XenStore initialisation for XS_LOCAL
iommu/vt-d: Gracefully handle DMAR units with no supported address
widths
Eyal Birger (1):
xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
Giacinto Cifelli (1):
net: usb: qmi_wwan: added support for Thales Cinterion PLSx3 modem
family
Greg Kroah-Hartman (1):
Linux 4.19.173
Ivan Vecera (1):
team: protect features update by RCU to avoid deadlock
Jay Zhou (1):
KVM: x86: get smi pending status correctly
Johannes Berg (4):
wext: fix NULL-ptr-dereference with cfg80211's lack of commit()
iwlwifi: pcie: use jiffies for memory read spin time limit
iwlwifi: pcie: reschedule in long-running memory reads
mac80211: pause TX while changing interface type
Josef Bacik (1):
nbd: freeze the queue while we're adding connections
Kai-Heng Feng (1):
ACPI: sysfs: Prefer "compatible" modalias
Kamal Heib (1):
RDMA/cxgb4: Fix the reported max_recv_sge value
Koen Vandeputte (1):
ARM: dts: imx6qdl-gw52xx: fix duplicate regulator naming
Laurent Badel (1):
PM: hibernate: flush swap writer after marking
Like Xu (1):
KVM: x86/pmu: Fix HW_REF_CPU_CYCLES event pseudo-encoding in
intel_arch_events[]
Lorenzo Bianconi (2):
mt7601u: fix kernel crash unplugging the device
mt7601u: fix rx buffer refcounting
Max Krummenacher (1):
ARM: imx: build suspend-imx6.S with arm instruction set
Pablo Neira Ayuso (1):
netfilter: nft_dynset: add timeout extension to template
Pan Bian (2):
NFC: fix resource leak when target index is invalid
NFC: fix possible resource leak
Pengcheng Yang (1):
tcp: fix TLP timer not set when CA_STATE changes from DISORDER to OPEN
Roger Pau Monne (2):
xen/privcmd: allow fetching resource sizes
xen-blkfront: allow discard-* nodes to be optional
Roi Dayan (1):
net/mlx5: Fix memory leak on flow table creation error flow
Sean Young (1):
media: rc: ensure that uevent can be read directly after rc device
register
Shmulik Ladkani (1):
xfrm: Fix oops in xfrm_replay_advance_bmp
Sudeep Holla (1):
drivers: soc: atmel: Avoid calling at91_soc_init on non AT91 SoCs
Takashi Iwai (1):
ALSA: hda/via: Apply the workaround generically for Clevo machines
Takeshi Misawa (1):
rxrpc: Fix memory leak in rxrpc_lookup_local
Trond Myklebust (1):
pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()
Makefile | 2 +-
arch/arm/boot/dts/imx6qdl-gw52xx.dtsi | 2 +-
arch/arm/mach-imx/suspend-imx6.S | 1 +
arch/x86/kvm/pmu_intel.c | 2 +-
arch/x86/kvm/x86.c | 5 +++
drivers/acpi/device_sysfs.c | 20 +++------
drivers/block/nbd.c | 8 ++++
drivers/block/xen-blkfront.c | 20 +++------
drivers/infiniband/hw/cxgb4/qp.c | 2 +-
drivers/iommu/dmar.c | 45 +++++++++++++------
drivers/leds/led-triggers.c | 10 +++--
drivers/media/rc/rc-main.c | 4 +-
drivers/net/can/dev.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fs_core.c | 1 +
drivers/net/team/team.c | 6 +--
drivers/net/usb/qmi_wwan.c | 1 +
.../net/wireless/intel/iwlwifi/pcie/trans.c | 14 +++---
drivers/net/wireless/mediatek/mt7601u/dma.c | 5 +--
drivers/soc/atmel/soc.c | 13 ++++++
drivers/xen/privcmd.c | 25 ++++++++---
drivers/xen/xenbus/xenbus_probe.c | 31 +++++++++++++
fs/nfs/pnfs.c | 1 +
include/linux/intel-iommu.h | 2 +
include/net/tcp.h | 2 +-
kernel/kexec_core.c | 2 -
kernel/power/swap.c | 2 +-
net/ipv4/tcp_input.c | 10 +++--
net/ipv4/tcp_recovery.c | 5 ++-
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/iface.c | 6 +++
net/netfilter/nft_dynset.c | 4 +-
net/nfc/netlink.c | 1 +
net/nfc/rawsock.c | 2 +-
net/rxrpc/call_accept.c | 1 +
net/wireless/wext-core.c | 5 ++-
net/xfrm/xfrm_input.c | 2 +-
net/xfrm/xfrm_policy.c | 4 +-
sound/pci/hda/patch_via.c | 2 +-
38 files changed, 183 insertions(+), 88 deletions(-)
--
2.25.1
1
38
07 Feb '21
From: Zheng Bin <zhengbin13(a)huawei.com>
stable inclusion
from linux-4.19.133
commit 306290bad932950adccfbf99c27b70c105c2c183
--------------------------------
[ Upstream commit 579dd91ab3a5446b148e7f179b6596b270dace46 ]
When adding first socket to nbd, if nsock's allocation failed, the data
structure member "config->socks" was reallocated, but the data structure
member "config->num_connections" was not updated. A memory leak will occur
then because the function "nbd_config_put" will free "config->socks" only
when "config->num_connections" is not zero.
Fixes: 03bf73c315ed ("nbd: prevent memory leak")
Reported-by: syzbot+934037347002901b8d2a(a)syzkaller.appspotmail.com
Signed-off-by: Zheng Bin <zhengbin13(a)huawei.com>
Reviewed-by: Eric Biggers <ebiggers(a)google.com>
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/block/nbd.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 49f98b9b2777..97fcb040056c 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -993,25 +993,26 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
test_bit(NBD_RT_BOUND, &config->runtime_flags))) {
dev_err(disk_to_dev(nbd->disk),
"Device being setup by another task");
- sockfd_put(sock);
- return -EBUSY;
+ err = -EBUSY;
+ goto put_socket;
+ }
+
+ nsock = kzalloc(sizeof(*nsock), GFP_KERNEL);
+ if (!nsock) {
+ err = -ENOMEM;
+ goto put_socket;
}
socks = krealloc(config->socks, (config->num_connections + 1) *
sizeof(struct nbd_sock *), GFP_KERNEL);
if (!socks) {
- sockfd_put(sock);
- return -ENOMEM;
+ kfree(nsock);
+ err = -ENOMEM;
+ goto put_socket;
}
config->socks = socks;
- nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL);
- if (!nsock) {
- sockfd_put(sock);
- return -ENOMEM;
- }
-
nsock->fallback_index = -1;
nsock->dead = false;
mutex_init(&nsock->tx_lock);
@@ -1023,6 +1024,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
atomic_inc(&config->live_connections);
return 0;
+
+put_socket:
+ sockfd_put(sock);
+ return err;
}
static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
--
2.25.1
1
1
[PATCH openEuler-1.0-LTS 1/7] futex: Ensure the correct return value from futex_lock_pi()
by Yang Yingliang 04 Feb '21
by Yang Yingliang 04 Feb '21
04 Feb '21
From: Thomas Gleixner <tglx(a)linutronix.de>
stable inclusion
from linux-4.19.172
commit 72f38fffa4758b878f819f8a47761b3f03443f36
CVE: CVE-2021-3347
--------------------------------
commit 12bb3f7f1b03d5913b3f9d4236a488aa7774dfe9 upstream
In case that futex_lock_pi() was aborted by a signal or a timeout and the
task returned without acquiring the rtmutex, but is the designated owner of
the futex due to a concurrent futex_unlock_pi() fixup_owner() is invoked to
establish consistent state. In that case it invokes fixup_pi_state_owner()
which in turn tries to acquire the rtmutex again. If that succeeds then it
does not propagate this success to fixup_owner() and futex_lock_pi()
returns -EINTR or -ETIMEOUT despite having the futex locked.
Return success from fixup_pi_state_owner() in all cases where the current
task owns the rtmutex and therefore the futex and propagate it correctly
through fixup_owner(). Fixup the other callsite which does not expect a
positive return value.
Fixes: c1e2f0eaf015 ("futex: Avoid violating the 10th rule of futex")
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz(a)infradead.org>
Cc: stable(a)vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Xiu Jianfeng <xiujianfeng(a)huawei.com>
Reviewed-by: Wei Li <liwei391(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
kernel/futex.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index 28b321e23053..ca9389bd110f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2414,8 +2414,8 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
}
if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
- /* We got the lock after all, nothing to fix. */
- ret = 0;
+ /* We got the lock. pi_state is correct. Tell caller. */
+ ret = 1;
goto out_unlock;
}
@@ -2431,7 +2431,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
* We raced against a concurrent self; things are
* already fixed up. Nothing to do.
*/
- ret = 0;
+ ret = 1;
goto out_unlock;
}
newowner = argowner;
@@ -2477,7 +2477,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
raw_spin_unlock(&newowner->pi_lock);
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
- return 0;
+ return argowner == current;
/*
* In order to reschedule or handle a page fault, we need to drop the
@@ -2519,7 +2519,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
* Check if someone else fixed it for us:
*/
if (pi_state->owner != oldowner) {
- ret = 0;
+ ret = argowner == current;
goto out_unlock;
}
@@ -2552,8 +2552,6 @@ static long futex_wait_restart(struct restart_block *restart);
*/
static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
{
- int ret = 0;
-
if (locked) {
/*
* Got the lock. We might not be the anticipated owner if we
@@ -2564,8 +2562,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
* stable state, anything else needs more attention.
*/
if (q->pi_state->owner != current)
- ret = fixup_pi_state_owner(uaddr, q, current);
- goto out;
+ return fixup_pi_state_owner(uaddr, q, current);
+ return 1;
}
/*
@@ -2576,10 +2574,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
* Another speculative read; pi_state->owner == current is unstable
* but needs our attention.
*/
- if (q->pi_state->owner == current) {
- ret = fixup_pi_state_owner(uaddr, q, NULL);
- goto out;
- }
+ if (q->pi_state->owner == current)
+ return fixup_pi_state_owner(uaddr, q, NULL);
/*
* Paranoia check. If we did not take the lock, then we should not be
@@ -2592,8 +2588,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
q->pi_state->owner);
}
-out:
- return ret ? ret : locked;
+ return 0;
}
/**
@@ -3315,7 +3310,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
if (q.pi_state && (q.pi_state->owner != current)) {
spin_lock(q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
- if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
+ if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
pi_state = q.pi_state;
get_pi_state(pi_state);
}
@@ -3325,6 +3320,11 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
*/
put_pi_state(q.pi_state);
spin_unlock(q.lock_ptr);
+ /*
+ * Adjust the return value. It's either -EFAULT or
+ * success (1) but the caller expects 0 for success.
+ */
+ ret = ret < 0 ? ret : 0;
}
} else {
struct rt_mutex *pi_mutex;
--
2.25.1
1
6
[PATCH openEuler-1.0-LTS 1/3] netfilter: clear skb->next in NF_HOOK_LIST()
by Yang Yingliang 04 Feb '21
by Yang Yingliang 04 Feb '21
04 Feb '21
From: Cong Wang <cong.wang(a)bytedance.com>
stable inclusion
from linux-4.19.161
commit 5460d62d661c0fc53bfe83493821b1dc3dc969f4
--------------------------------
NF_HOOK_LIST() uses list_del() to remove skb from the linked list,
however, it is not sufficient as skb->next still points to other
skb. We should just call skb_list_del_init() to clear skb->next,
like the rest places which using skb list.
This has been fixed in upstream by commit ca58fbe06c54
("netfilter: add and use nf_hook_slow_list()").
Fixes: 9f17dbf04ddf ("netfilter: fix use-after-free in NF_HOOK_LIST")
Reported-by: liuzx(a)knownsec.com
Tested-by: liuzx(a)knownsec.com
Cc: Florian Westphal <fw(a)strlen.de>
Cc: Edward Cree <ecree(a)solarflare.com>
Cc: stable(a)vger.kernel.org # between 4.19 and 5.4
Signed-off-by: Cong Wang <cong.wang(a)bytedance.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/netfilter.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 72cb19c3db6a..9460a5635c90 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -300,7 +300,7 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
INIT_LIST_HEAD(&sublist);
list_for_each_entry_safe(skb, next, head, list) {
- list_del(&skb->list);
+ skb_list_del_init(skb);
if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1)
list_add_tail(&skb->list, &sublist);
}
--
2.25.1
1
2
04 Feb '21
From: Mark Rutland <mark.rutland(a)arm.com>
mainline inclusion
from mainline-v5.5-rc1
commit bd8b21d3dd661658addc1cd4cc869bab11d28596
category: bugfix
bugzilla: 25285
CVE: NA
--------------------------------
When we load a module, we have to perform some special work for a couple
of named sections. To do this, we iterate over all of the module's
sections, and perform work for each section we recognize.
To make it easier to handle the unexpected absence of a section, and to
make the section-specific logic easer to read, let's factor the section
search into a helper. Similar is already done in the core module loader,
and other architectures (and ideally we'd unify these in future).
If we expect a module to have an ftrace trampoline section, but it
doesn't have one, we'll now reject loading the module. When
ARM64_MODULE_PLTS is selected, any correctly built module should have
one (and this is assumed by arm64's ftrace PLT code) and the absence of
such a section implies something has gone wrong at build time.
Subsequent patches will make use of the new helper.
Signed-off-by: Mark Rutland <mark.rutland(a)arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel(a)linaro.org>
Reviewed-by: Torsten Duwe <duwe(a)suse.de>
Tested-by: Amit Daniel Kachhap <amit.kachhap(a)arm.com>
Tested-by: Torsten Duwe <duwe(a)suse.de>
Cc: Catalin Marinas <catalin.marinas(a)arm.com>
Cc: James Morse <james.morse(a)arm.com>
Cc: Will Deacon <will(a)kernel.org>
Signed-off-by: Pu Lehui <pulehui(a)huawei.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/arm64/kernel/module.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 834ecf108b53..55b00bfb704f 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -484,22 +484,39 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
return -ENOEXEC;
}
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
+static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ const char *name)
{
const Elf_Shdr *s, *se;
const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
- if (strcmp(".altinstructions", secstrs + s->sh_name) == 0)
- apply_alternatives_module((void *)s->sh_addr, s->sh_size);
+ if (strcmp(name, secstrs + s->sh_name) == 0)
+ return s;
+ }
+
+ return NULL;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ const Elf_Shdr *s;
+
+ s = find_section(hdr, sechdrs, ".altinstructions");
+ if (s)
+ apply_alternatives_module((void *)s->sh_addr, s->sh_size);
+
#ifdef CONFIG_ARM64_MODULE_PLTS
- if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE) &&
- !strcmp(".text.ftrace_trampoline", secstrs + s->sh_name))
- me->arch.ftrace_trampoline = (void *)s->sh_addr;
-#endif
+ if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE)) {
+ s = find_section(hdr, sechdrs, ".text.ftrace_trampoline");
+ if (!s)
+ return -ENOEXEC;
+ me->arch.ftrace_trampoline = (void *)s->sh_addr;
}
+#endif
return 0;
}
--
2.25.1
1
3
Baruch Siach (1):
gpio: mvebu: fix pwm .get_state period calculation
Eric Biggers (1):
fs: fix lazytime expiration handling in __writeback_single_inode()
Gaurav Kohli (1):
tracing: Fix race in trace_open and buffer resize call
Greg Kroah-Hartman (1):
Linux 4.19.172
Jan Kara (1):
writeback: Drop I_DIRTY_TIME_EXPIRE
Jason Gerecke (1):
HID: wacom: Correct NULL dereference on AES pen proximity
Jean-Philippe Brucker (1):
tools: Factor HOSTCC, HOSTLD, HOSTAR definitions
Mikulas Patocka (1):
dm integrity: conditionally disable "recalculate" feature
Thomas Gleixner (18):
futex: Move futex exit handling into futex code
futex: Replace PF_EXITPIDONE with a state
exit/exec: Seperate mm_release()
futex: Split futex_mm_release() for exit/exec
futex: Set task::futex_state to DEAD right after handling futex exit
futex: Mark the begin of futex exit explicitly
futex: Sanitize exit state handling
futex: Provide state handling for exec() as well
futex: Add mutex around futex exit
futex: Provide distinct return value when owner is exiting
futex: Prevent exit livelock
futex: Ensure the correct return value from futex_lock_pi()
futex: Replace pointless printk in fixup_owner()
futex: Provide and use pi_state_update_owner()
rtmutex: Remove unused argument from rt_mutex_proxy_unlock()
futex: Use pi_state_update_owner() in put_pi_state()
futex: Simplify fixup_pi_state_owner()
futex: Handle faults correctly for PI futexes
Wang Hai (1):
Revert "mm/slub: fix a memory leak in sysfs_slab_add()"
Documentation/device-mapper/dm-integrity.txt | 7 +
Makefile | 2 +-
drivers/gpio/gpio-mvebu.c | 25 +-
drivers/hid/wacom_sys.c | 7 +-
drivers/hid/wacom_wac.h | 2 +-
drivers/md/dm-integrity.c | 24 +-
fs/exec.c | 2 +-
fs/ext4/inode.c | 2 +-
fs/fs-writeback.c | 36 +-
fs/xfs/xfs_trans_inode.c | 4 +-
include/linux/compat.h | 2 -
include/linux/fs.h | 1 -
include/linux/futex.h | 40 +-
include/linux/sched.h | 3 +-
include/linux/sched/mm.h | 6 +-
include/trace/events/writeback.h | 1 -
kernel/exit.c | 30 +-
kernel/fork.c | 40 +-
kernel/futex.c | 485 +++++++++++++------
kernel/locking/rtmutex.c | 3 +-
kernel/locking/rtmutex_common.h | 3 +-
kernel/trace/ring_buffer.c | 4 +
mm/slub.c | 4 +-
tools/build/Makefile | 4 -
tools/objtool/Makefile | 9 -
tools/perf/Makefile.perf | 4 -
tools/power/acpi/Makefile.config | 1 -
tools/scripts/Makefile.include | 10 +
28 files changed, 459 insertions(+), 302 deletions(-)
--
2.25.1
1
27
04 Feb '21
From: Florian Westphal <fw(a)strlen.de>
mainline inclusion
from mainline-v5.5-rc1
commit ca58fbe06c54795f00db79e447f94c2028d30124
category: bugfix
bugzilla: NA
CVE: CVE-2021-20177
--------------------------------
At this time, NF_HOOK_LIST() macro will iterate the list and then calls
nf_hook() for each individual skb.
This makes it so the entire list is passed into the netfilter core.
The advantage is that we only need to fetch the rule blob once per list
instead of per-skb.
NF_HOOK_LIST now only works for ipv4 and ipv6, as those are the only
callers.
v2: use skb_list_del_init() instead of list_del (Edward Cree)
Signed-off-by: Florian Westphal <fw(a)strlen.de>
Acked-by: Edward Cree <ecree(a)solarflare.com>
Signed-off-by: Pablo Neira Ayuso <pablo(a)netfilter.org>
Conflicts:
include/linux/netfilter.h
net/netfilter/core.c
[yyl: adjust context]
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Yue Haibing <yuehaibing(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/netfilter.h | 41 +++++++++++++++++++++++++++++----------
net/netfilter/core.c | 20 +++++++++++++++++++
2 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 9460a5635c90..8bf57abee9e4 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -183,6 +183,8 @@ extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
const struct nf_hook_entries *e, unsigned int i);
+void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state,
+ const struct nf_hook_entries *e);
/**
* nf_hook - call a netfilter hook
*
@@ -295,17 +297,36 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
struct list_head *head, struct net_device *in, struct net_device *out,
int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
- struct sk_buff *skb, *next;
- struct list_head sublist;
-
- INIT_LIST_HEAD(&sublist);
- list_for_each_entry_safe(skb, next, head, list) {
- skb_list_del_init(skb);
- if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1)
- list_add_tail(&skb->list, &sublist);
+ struct nf_hook_entries *hook_head = NULL;
+
+#ifdef CONFIG_JUMP_LABEL
+ if (__builtin_constant_p(pf) &&
+ __builtin_constant_p(hook) &&
+ !static_key_false(&nf_hooks_needed[pf][hook]))
+ return;
+#endif
+
+ rcu_read_lock();
+ switch (pf) {
+ case NFPROTO_IPV4:
+ hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]);
+ break;
+ case NFPROTO_IPV6:
+ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
}
- /* Put passed packets back on main list */
- list_splice(&sublist, head);
+
+ if (hook_head) {
+ struct nf_hook_state state;
+
+ nf_hook_state_init(&state, hook, pf, in, out, sk, net, okfn);
+
+ nf_hook_slow_list(head, &state, hook_head);
+ }
+ rcu_read_unlock();
}
/* Call setsockopt() */
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 93aaec3a54ec..3f0bdc728f89 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -536,6 +536,26 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
EXPORT_SYMBOL(nf_hook_slow);
+void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state,
+ const struct nf_hook_entries *e)
+{
+ struct sk_buff *skb, *next;
+ struct list_head sublist;
+ int ret;
+
+ INIT_LIST_HEAD(&sublist);
+
+ list_for_each_entry_safe(skb, next, head, list) {
+ skb_list_del_init(skb);
+ ret = nf_hook_slow(skb, state, e, 0);
+ if (ret == 1)
+ list_add_tail(&skb->list, &sublist);
+ }
+ /* Put passed packets back on main list */
+ list_splice(&sublist, head);
+}
+EXPORT_SYMBOL(nf_hook_slow_list);
+
int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
{
if (writable_len > skb->len)
--
2.25.1
1
1
[PATCH openEuler-1.0-LTS] scsi: target: Fix XCOPY NAA identifier lookup
by Yang Yingliang 04 Feb '21
by Yang Yingliang 04 Feb '21
04 Feb '21
From: David Disseldorp <ddiss(a)suse.de>
stable inclusion
from linux-4.19.167
commit fff1180d24e68d697f98642d71444316036a81ff
CVE: CVE-2020-28374
--------------------------------
commit 2896c93811e39d63a4d9b63ccf12a8fbc226e5e4 upstream.
When attempting to match EXTENDED COPY CSCD descriptors with corresponding
se_devices, target_xcopy_locate_se_dev_e4() currently iterates over LIO's
global devices list which includes all configured backstores.
This change ensures that only initiator-accessible backstores are
considered during CSCD descriptor lookup, according to the session's
se_node_acl LUN list.
To avoid LUN removal race conditions, device pinning is changed from being
configfs based to instead using the se_node_acl lun_ref.
Reference: CVE-2020-28374
Fixes: cbf031f425fd ("target: Add support for EXTENDED_COPY copy offload emulation")
Reviewed-by: Lee Duncan <lduncan(a)suse.com>
Signed-off-by: David Disseldorp <ddiss(a)suse.de>
Signed-off-by: Mike Christie <michael.christie(a)oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen(a)oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/target/target_core_xcopy.c | 119 +++++++++++++++++------------
drivers/target/target_core_xcopy.h | 1 +
2 files changed, 71 insertions(+), 49 deletions(-)
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 7cdb5d7f6538..1709b8a99bd7 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -55,60 +55,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
return 0;
}
-struct xcopy_dev_search_info {
- const unsigned char *dev_wwn;
- struct se_device *found_dev;
-};
-
+/**
+ * target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers
+ *
+ * @se_dev: device being considered for match
+ * @dev_wwn: XCOPY requested NAA dev_wwn
+ * @return: 1 on match, 0 on no-match
+ */
static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev,
- void *data)
+ const unsigned char *dev_wwn)
{
- struct xcopy_dev_search_info *info = data;
unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
int rc;
- if (!se_dev->dev_attrib.emulate_3pc)
+ if (!se_dev->dev_attrib.emulate_3pc) {
+ pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev);
return 0;
+ }
memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
- rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
- if (rc != 0)
- return 0;
-
- info->found_dev = se_dev;
- pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
-
- rc = target_depend_item(&se_dev->dev_group.cg_item);
+ rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
if (rc != 0) {
- pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n",
- rc, se_dev);
- return rc;
+ pr_debug("XCOPY: skip non-matching: %*ph\n",
+ XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
+ return 0;
}
+ pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
- pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n",
- se_dev, &se_dev->dev_group);
return 1;
}
-static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
- struct se_device **found_dev)
+static int target_xcopy_locate_se_dev_e4(struct se_session *sess,
+ const unsigned char *dev_wwn,
+ struct se_device **_found_dev,
+ struct percpu_ref **_found_lun_ref)
{
- struct xcopy_dev_search_info info;
- int ret;
-
- memset(&info, 0, sizeof(info));
- info.dev_wwn = dev_wwn;
-
- ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info);
- if (ret == 1) {
- *found_dev = info.found_dev;
- return 0;
- } else {
- pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
- return -EINVAL;
+ struct se_dev_entry *deve;
+ struct se_node_acl *nacl;
+ struct se_lun *this_lun = NULL;
+ struct se_device *found_dev = NULL;
+
+ /* cmd with NULL sess indicates no associated $FABRIC_MOD */
+ if (!sess)
+ goto err_out;
+
+ pr_debug("XCOPY 0xe4: searching for: %*ph\n",
+ XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn);
+
+ nacl = sess->se_node_acl;
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
+ struct se_device *this_dev;
+ int rc;
+
+ this_lun = rcu_dereference(deve->se_lun);
+ this_dev = rcu_dereference_raw(this_lun->lun_se_dev);
+
+ rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn);
+ if (rc) {
+ if (percpu_ref_tryget_live(&this_lun->lun_ref))
+ found_dev = this_dev;
+ break;
+ }
}
+ rcu_read_unlock();
+ if (found_dev == NULL)
+ goto err_out;
+
+ pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n",
+ found_dev, &found_dev->dev_group);
+ *_found_dev = found_dev;
+ *_found_lun_ref = &this_lun->lun_ref;
+ return 0;
+err_out:
+ pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
+ return -EINVAL;
}
static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
@@ -255,12 +278,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
switch (xop->op_origin) {
case XCOL_SOURCE_RECV_OP:
- rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
- &xop->dst_dev);
+ rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
+ xop->dst_tid_wwn,
+ &xop->dst_dev,
+ &xop->remote_lun_ref);
break;
case XCOL_DEST_RECV_OP:
- rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
- &xop->src_dev);
+ rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
+ xop->src_tid_wwn,
+ &xop->src_dev,
+ &xop->remote_lun_ref);
break;
default:
pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
@@ -412,18 +439,12 @@ static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
{
- struct se_device *remote_dev;
-
if (xop->op_origin == XCOL_SOURCE_RECV_OP)
- remote_dev = xop->dst_dev;
+ pr_debug("putting dst lun_ref for %p\n", xop->dst_dev);
else
- remote_dev = xop->src_dev;
-
- pr_debug("Calling configfs_undepend_item for"
- " remote_dev: %p remote_dev->dev_group: %p\n",
- remote_dev, &remote_dev->dev_group.cg_item);
+ pr_debug("putting src lun_ref for %p\n", xop->src_dev);
- target_undepend_item(&remote_dev->dev_group.cg_item);
+ percpu_ref_put(xop->remote_lun_ref);
}
static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
diff --git a/drivers/target/target_core_xcopy.h b/drivers/target/target_core_xcopy.h
index 26ba4c3c9cff..974bc1e19ff2 100644
--- a/drivers/target/target_core_xcopy.h
+++ b/drivers/target/target_core_xcopy.h
@@ -29,6 +29,7 @@ struct xcopy_op {
struct se_device *dst_dev;
unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
+ struct percpu_ref *remote_lun_ref;
sector_t src_lba;
sector_t dst_lba;
--
2.25.1
1
0
30 Jan '21
From: Florian Westphal <fw(a)strlen.de>
mainline inclusion
from mainline-v5.5-rc1
commit ca58fbe06c54795f00db79e447f94c2028d30124
category: bugfix
bugzilla: NA
CVE: CVE-2021-20177
--------------------------------
At this time, NF_HOOK_LIST() macro will iterate the list and then calls
nf_hook() for each individual skb.
This makes it so the entire list is passed into the netfilter core.
The advantage is that we only need to fetch the rule blob once per list
instead of per-skb.
NF_HOOK_LIST now only works for ipv4 and ipv6, as those are the only
callers.
v2: use skb_list_del_init() instead of list_del (Edward Cree)
Signed-off-by: Florian Westphal <fw(a)strlen.de>
Acked-by: Edward Cree <ecree(a)solarflare.com>
Signed-off-by: Pablo Neira Ayuso <pablo(a)netfilter.org>
Conflicts:
include/linux/netfilter.h
net/netfilter/core.c
[yyl: adjust context]
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Yue Haibing <yuehaibing(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/netfilter.h | 41 +++++++++++++++++++++++++++++----------
net/netfilter/core.c | 20 +++++++++++++++++++
2 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 9460a5635c90..8bf57abee9e4 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -183,6 +183,8 @@ extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
const struct nf_hook_entries *e, unsigned int i);
+void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state,
+ const struct nf_hook_entries *e);
/**
* nf_hook - call a netfilter hook
*
@@ -295,17 +297,36 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
struct list_head *head, struct net_device *in, struct net_device *out,
int (*okfn)(struct net *, struct sock *, struct sk_buff *))
{
- struct sk_buff *skb, *next;
- struct list_head sublist;
-
- INIT_LIST_HEAD(&sublist);
- list_for_each_entry_safe(skb, next, head, list) {
- skb_list_del_init(skb);
- if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1)
- list_add_tail(&skb->list, &sublist);
+ struct nf_hook_entries *hook_head = NULL;
+
+#ifdef CONFIG_JUMP_LABEL
+ if (__builtin_constant_p(pf) &&
+ __builtin_constant_p(hook) &&
+ !static_key_false(&nf_hooks_needed[pf][hook]))
+ return;
+#endif
+
+ rcu_read_lock();
+ switch (pf) {
+ case NFPROTO_IPV4:
+ hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]);
+ break;
+ case NFPROTO_IPV6:
+ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
}
- /* Put passed packets back on main list */
- list_splice(&sublist, head);
+
+ if (hook_head) {
+ struct nf_hook_state state;
+
+ nf_hook_state_init(&state, hook, pf, in, out, sk, net, okfn);
+
+ nf_hook_slow_list(head, &state, hook_head);
+ }
+ rcu_read_unlock();
}
/* Call setsockopt() */
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 93aaec3a54ec..3f0bdc728f89 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -536,6 +536,26 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
EXPORT_SYMBOL(nf_hook_slow);
+void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state,
+ const struct nf_hook_entries *e)
+{
+ struct sk_buff *skb, *next;
+ struct list_head sublist;
+ int ret;
+
+ INIT_LIST_HEAD(&sublist);
+
+ list_for_each_entry_safe(skb, next, head, list) {
+ skb_list_del_init(skb);
+ ret = nf_hook_slow(skb, state, e, 0);
+ if (ret == 1)
+ list_add_tail(&skb->list, &sublist);
+ }
+ /* Put passed packets back on main list */
+ list_splice(&sublist, head);
+}
+EXPORT_SYMBOL(nf_hook_slow_list);
+
int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
{
if (writable_len > skb->len)
--
2.25.1
1
1
Alex Leibovich (1):
mmc: sdhci-xenon: fix 1.8v regulator stabilization
Alexander Lobakin (1):
skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
Alexander Shishkin (1):
intel_th: pci: Add Alder Lake-P support
Arnd Bergmann (1):
scsi: megaraid_sas: Fix MEGASAS_IOC_FIRMWARE regression
Ben Skeggs (5):
drm/nouveau/bios: fix issue shadowing expansion ROMs
drm/nouveau/privring: ack interrupts the same way as RM
drm/nouveau/i2c/gm200: increase width of aux semaphore owner fields
drm/nouveau/mmu: fix vram heap sizing
drm/nouveau/kms/nv50-: fix case where notifier buffer is at offset 0
Can Guo (1):
scsi: ufs: Correct the LUN used in eh_device_reset_handler() callback
Cezary Rojewski (1):
ASoC: Intel: haswell: Add missing pm_ops
Damien Le Moal (1):
riscv: Fix kernel time_init()
Dan Carpenter (1):
net: dsa: b53: fix an off by one in checking "vlan->vid"
David Woodhouse (1):
xen: Fix event channel callback via INTX/GSI
Eric Dumazet (2):
net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
net_sched: reject silly cell_log in qdisc_get_rtab()
Eugene Korenevsky (1):
ehci: fix EHCI host controller initialization sequence
Geert Uytterhoeven (1):
sh_eth: Fix power down vs. is_opened flag ordering
Greg Kroah-Hartman (1):
Linux 4.19.171
Guillaume Nault (2):
netfilter: rpfilter: mask ecn bits before fib lookup
udp: mask TOS bits in udp_v4_early_demux()
Hangbin Liu (1):
selftests: net: fib_tests: remove duplicate log test
Hannes Reinecke (1):
dm: avoid filesystem lookup in dm_get_dev_t()
Hans de Goede (2):
ACPI: scan: Make acpi_bus_get_device() clear return pointer on error
platform/x86: intel-vbtn: Drop HP Stream x360 Convertible PC 11 from
allow-list
JC Kuo (1):
xhci: tegra: Delay for disabling LFPS detector
Josef Bacik (1):
btrfs: fix lockdep splat in btrfs_recover_relocation
Lars-Peter Clausen (1):
iio: ad5504: Fix setting power-down state
Lecopzer Chen (2):
kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
kasan: fix incorrect arguments passing in kasan_add_zero_shadow
Longfang Liu (1):
USB: ehci: fix an interrupt calltrace error
Mathias Kresin (1):
irqchip/mips-cpu: Set IPI domain parent chip
Mathias Nyman (1):
xhci: make sure TRB is fully written before giving it to the
controller
Matteo Croce (2):
ipv6: create multicast route with RTPROT_KERNEL
ipv6: set multicast flag on the multicast route
Mikko Perttunen (1):
i2c: bpmp-tegra: Ignore unknown I2C_M flags
Mikulas Patocka (1):
dm integrity: fix a crash if "recalculate" used without
"internal_hash"
Necip Fazil Yildiran (1):
sh: dma: fix kconfig dependency for G2_DMA
Nilesh Javali (1):
scsi: qedi: Correct max length of CHAP secret
Pali Rohár (1):
serial: mvebu-uart: fix tx lost characters at power off
Pan Bian (1):
drm/atomic: put state on error path
Patrik Jakobsson (1):
usb: bdc: Make bdc pci driver depend on BROKEN
Peter Collingbourne (1):
mmc: core: don't initialize block size from ext_csd if not present
Peter Geis (1):
clk: tegra30: Add hda clock default rates to clock driver
Rafael J. Wysocki (1):
driver core: Extend device_is_dependent()
Ryan Chen (1):
usb: gadget: aspeed: fix stop dma register setting.
Seth Miller (1):
HID: Ignore battery for Elan touchscreen on ASUS UX550
Takashi Iwai (2):
ALSA: seq: oss: Fix missing error check in
snd_seq_oss_synth_make_info()
ALSA: hda/via: Add minimum mute flag
Tariq Toukan (1):
net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
Thinh Nguyen (1):
usb: udc: core: Use lock when write to soft_connect
Vincent Mailhol (3):
can: dev: can_restart: fix use after free bug
can: vxcan: vxcan_xmit: fix use after free bug
can: peak_usb: fix use after free bugs
Vladimir Oltean (1):
net: mscc: ocelot: allow offloading of bridge on top of LAG
Wang Hui (1):
stm class: Fix module init return on allocation failure
Wolfram Sang (1):
i2c: octeon: check correct size of maximum RECV_LEN packet
Makefile | 2 +-
arch/arm/xen/enlighten.c | 2 +-
arch/riscv/kernel/time.c | 3 +
arch/sh/drivers/dma/Kconfig | 3 +-
drivers/acpi/scan.c | 2 +
drivers/base/core.c | 17 +++-
drivers/clk/tegra/clk-tegra30.c | 2 +
drivers/gpu/drm/drm_atomic_helper.c | 2 +-
drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 +-
drivers/gpu/drm/nouveau/dispnv50/disp.h | 2 +-
drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c | 2 +-
.../gpu/drm/nouveau/nvkm/subdev/bios/shadow.c | 2 +-
.../drm/nouveau/nvkm/subdev/i2c/auxgm200.c | 8 +-
.../gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c | 10 ++-
.../gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c | 10 ++-
.../gpu/drm/nouveau/nvkm/subdev/mmu/base.c | 6 +-
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-input.c | 2 +
drivers/hwtracing/intel_th/pci.c | 5 ++
drivers/hwtracing/stm/heartbeat.c | 6 +-
drivers/i2c/busses/i2c-octeon-core.c | 2 +-
drivers/i2c/busses/i2c-tegra-bpmp.c | 2 +-
drivers/iio/dac/ad5504.c | 4 +-
drivers/irqchip/irq-mips-cpu.c | 7 ++
drivers/md/dm-integrity.c | 6 ++
drivers/md/dm-table.c | 15 +++-
drivers/mmc/core/queue.c | 4 +-
drivers/mmc/host/sdhci-xenon.c | 7 +-
drivers/net/can/dev.c | 4 +-
drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 8 +-
drivers/net/can/vxcan.c | 6 +-
drivers/net/dsa/b53/b53_common.c | 2 +-
drivers/net/ethernet/mscc/ocelot.c | 4 +-
drivers/net/ethernet/renesas/sh_eth.c | 4 +-
drivers/platform/x86/intel-vbtn.c | 6 --
drivers/scsi/megaraid/megaraid_sas_base.c | 6 +-
drivers/scsi/qedi/qedi_main.c | 4 +-
drivers/scsi/ufs/ufshcd.c | 11 +--
drivers/tty/serial/mvebu-uart.c | 10 ++-
drivers/usb/gadget/udc/aspeed-vhub/epn.c | 5 +-
drivers/usb/gadget/udc/bdc/Kconfig | 2 +-
drivers/usb/gadget/udc/core.c | 13 ++-
drivers/usb/host/ehci-hcd.c | 12 +++
drivers/usb/host/ehci-hub.c | 3 +
drivers/usb/host/xhci-ring.c | 2 +
drivers/usb/host/xhci-tegra.c | 7 ++
drivers/xen/events/events_base.c | 10 ---
drivers/xen/platform-pci.c | 1 -
drivers/xen/xenbus/xenbus.h | 1 +
drivers/xen/xenbus/xenbus_comms.c | 8 --
drivers/xen/xenbus/xenbus_probe.c | 81 +++++++++++++++----
fs/btrfs/volumes.c | 2 +
include/xen/xenbus.h | 2 +-
mm/kasan/kasan_init.c | 23 +++---
net/core/dev.c | 5 ++
net/core/skbuff.c | 6 +-
net/ipv4/netfilter/ipt_rpfilter.c | 2 +-
net/ipv4/udp.c | 3 +-
net/ipv6/addrconf.c | 3 +-
net/sched/cls_tcindex.c | 8 +-
net/sched/sch_api.c | 3 +-
sound/core/seq/oss/seq_oss_synth.c | 3 +-
sound/pci/hda/patch_via.c | 1 +
sound/soc/intel/boards/haswell.c | 1 +
tools/testing/selftests/net/fib_tests.sh | 1 -
65 files changed, 284 insertions(+), 127 deletions(-)
--
2.25.1
1
57
Hi,
In Linux 5.8, Nick submitted a patch-set to fix some Errors in symbol search when you try to profile JIT compiled application in OpenJDK with perf.
The patchset is:
1e4bd2ae4564 perf jit: Fix inaccurate DWARF line table
7d7e503cac31 perf jvmti: Remove redundant jitdump line table entries
0bdf31811be0 perf jvmti: Fix demangling Java symbols
525c821de0a6 perf tests: Add test for the java demangler
959f8ed4c1a8 perf jvmti: Do not report error when missing debug information
953e92402a52 perf jvmti: Fix jitdump for methods without debug info
Because making perf work is very useful for performance analysis on JITed Java application, I'd like to support this patchset in openEuler release.
The coming 21.03 should be a first target as that release is upgraded with 5.8+ kernel.
Probably we can backport this patchset to 20.03 LTS if needed.
To introduce the fix to 21.03, the kernel.spec should be changed with some lines to generate the JVMTI shared library.
There are some things I am not sure:
1. kernel.spec is in src-openeuler project, do I submit the change by PR or by sending patch directly to the mailing list?
2. Is there rolling release of openEuler like Tumbleweed? Then we can run some tests with the daily ISO before the stable 21.03
And one more question, has version 21.03 created a build project in openEuler OBS??
Is it this one?
https://build.openeuler.org/package/show/openEuler:Mainline/kernel
Thanks,
Erik
3
5
Andrey Zhizhikin (1):
rndis_host: set proper input size for OID_GEN_PHYSICAL_MEDIUM request
Arnd Bergmann (1):
crypto: x86/crc32c - fix building with clang ias
Aya Levin (1):
net: ipv6: Validate GSO SKB before finish IPv6 processing
Baptiste Lepers (2):
udp: Prevent reuseport_select_sock from reading uninitialized socks
rxrpc: Call state should be read with READ_ONCE() under some
circumstances
David Howells (1):
rxrpc: Fix handling of an unsupported token type in rxrpc_read()
David Wu (1):
net: stmmac: Fixed mtu channged by cache aligned
Eric Dumazet (1):
net: avoid 32 x truesize under-estimation for tiny skbs
Greg Kroah-Hartman (1):
Linux 4.19.170
Hamish Martin (1):
usb: ohci: Make distrust_firmware param default to false
Hoang Le (1):
tipc: fix NULL deref in tipc_link_xmit()
Jakub Kicinski (1):
net: sit: unregister_netdevice on newlink's error path
Jason A. Donenfeld (2):
net: introduce skb_list_walk_safe for skb segment walking
net: skbuff: disambiguate argument and member for skb_list_walk_safe
helper
Manish Chopra (1):
netxen_nic: fix MSI/MSI-x interrupts
Michael Hennerich (1):
spi: cadence: cache reference clock rate during probe
Mikulas Patocka (1):
dm integrity: fix flush with external metadata device
Petr Machata (2):
net: dcb: Validate netlink message in DCB handler
net: dcb: Accept RTM_GETDCB messages carrying set-like DCB commands
Stefan Chulski (1):
net: mvpp2: Remove Pause and Asym_Pause support
Will Deacon (1):
compiler.h: Raise minimum version of GCC to 5.1 for arm64
Willem de Bruijn (1):
esp: avoid unneeded kmap_atomic call
Makefile | 2 +-
arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 2 +-
drivers/md/dm-bufio.c | 6 +++
drivers/md/dm-integrity.c | 50 +++++++++++++++++--
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 -
.../ethernet/qlogic/netxen/netxen_nic_main.c | 7 +--
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +-
drivers/net/usb/rndis_host.c | 2 +-
drivers/spi/spi-cadence.c | 6 ++-
drivers/usb/host/ohci-hcd.c | 2 +-
include/linux/compiler-gcc.h | 6 +++
include/linux/dm-bufio.h | 1 +
include/linux/skbuff.h | 5 ++
net/core/skbuff.c | 9 +++-
net/core/sock_reuseport.c | 2 +-
net/dcb/dcbnl.c | 2 +
net/ipv4/esp4.c | 7 +--
net/ipv6/esp6.c | 7 +--
net/ipv6/ip6_output.c | 40 ++++++++++++++-
net/ipv6/sit.c | 5 +-
net/rxrpc/input.c | 2 +-
net/rxrpc/key.c | 6 ++-
net/tipc/link.c | 9 +++-
23 files changed, 141 insertions(+), 42 deletions(-)
--
2.25.1
1
23
28 Jan '21
> I think you should remove the VM_CHECKNODE to set_vm_checknode
> set_vm_checknode(vm_flags_t *vm_flags, unsigned long flags)
> {
> if (flags & VM_CHECKNODE && is_set_cdmmask())
> *vm_flags |= VM_CHECKNODE | ((((flags >> MAP_HUGE_SHIFT) &
> MAP_HUGE_MASK) << CHECKNODE_BITS) & CHECKNODE_MASK);
> }
VM_CHECKNODE has been checked before the set_vm_checknode function is used.
Maybe we can put the check into set_vm_checknode(). What do you think?
mm/mmap.c
if (flags & MAP_CHECKNODE)
set_vm_checknode(&vm_flags, flags);
Thanks,
Bixuan Cui
1
0
[PATCH kernel-4.19] clocksource/drivers/arch_timer: Fix vdso_fix compile error for arm32
by Yang Yingliang 28 Jan '21
by Yang Yingliang 28 Jan '21
28 Jan '21
From: Hanjun Guo <guohanjun(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 47461
CVE: NA
-------------------------------------------------
We got compile error:
drivers/clocksource/arm_arch_timer.c: In function
'arch_counter_register':
drivers/clocksource/arm_arch_timer.c:1009:31: error: 'struct
arch_clocksource_data' has no member named 'vdso_fix'
1009 | clocksource_counter.archdata.vdso_fix = vdso_fix;
| ^
make[3]: ***
[/builds/1mzfdQzleCy69KZFb5qHNSEgabZ/scripts/Makefile.build:303:
drivers/clocksource/arm_arch_timer.o] Error 1
make[3]: Target '__build' not remade because of errors.
Fix it by guarding vdso_fix with #ifdef CONFIG_ARM64 .. #endif
Signed-off-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/clocksource/arm_arch_timer.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index d72ade5c70801..6847a5fe13fde 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1010,7 +1010,9 @@ static void __init arch_counter_register(unsigned type)
arch_timer_read_counter = arch_counter_get_cntpct;
clocksource_counter.archdata.vdso_direct = vdso_default;
+#ifdef CONFIG_ARM64
clocksource_counter.archdata.vdso_fix = vdso_fix;
+#endif
} else {
arch_timer_read_counter = arch_counter_get_cntvct_mem;
}
--
2.25.1
1
0
28 Jan '21
From: miaoyubo <miaoyubo(a)huawei.com>
virt inclusion
category: bugfix
bugzilla: 47428
CVE: NA
Disable PUD_SIZE huge mapping on 161x serial boards and only
enable on 1620CS due to low performance on cache maintenance
and complex implementation for pre-setup stage2 page table with
PUD huge page. Which would even lead to hard lockup
Signed-off-by: Zenghui Yu <yuzenghui(a)huawei.com>
Signed-off-by: miaoyubo <miaoyubo(a)huawei.com>
Reviewed-by: zhanghailiang <zhang.zhanghailiang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
virt/kvm/arm/mmu.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 3a74cf59f5c85..b030bd3dce52c 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1763,6 +1763,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (vma_pagesize == PMD_SIZE ||
(vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm)))
gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
+
+ /* Only enable PUD_SIZE huge mapping on 1620 serial boards */
+ if (vma_pagesize == PUD_SIZE && !kvm_ncsnp_support) {
+ vma_pagesize = PMD_SIZE;
+ gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT;
+ }
+
up_read(¤t->mm->mmap_sem);
/* We need minimum second+third level pages */
--
2.25.1
1
3
Akilesh Kailash (1):
dm snapshot: flush merged data before committing metadata
Al Viro (1):
dump_common_audit_data(): fix racy accesses to ->d_name
Alexander Lobakin (1):
MIPS: relocatable: fix possible boot hangup with KASLR enabled
Arnd Bergmann (2):
misdn: dsp: select CONFIG_BITREVERSE
ARM: picoxcell: fix missing interrupt-parent properties
Craig Tatlor (1):
drm/msm: Call msm_init_vram before binding the gpu
Dan Carpenter (1):
ASoC: Intel: fix error code cnl_set_dsp_D0()
Dave Wysochanski (1):
NFS4: Fix use-after-free in trace_event_raw_event_nfs4_set_lock
Dexuan Cui (1):
ACPI: scan: Harden acpi_device_add() against device ID overflows
Dinghao Liu (2):
RDMA/usnic: Fix memleak in find_free_vf_and_create_qp_grp
netfilter: nf_nat: Fix memleak in nf_nat_init
Filipe Manana (1):
btrfs: fix transaction leak and crash after RO remount caused by
qgroup rescan
Geert Uytterhoeven (2):
ALSA: firewire-tascam: Fix integer overflow in midi_port_work()
ALSA: fireface: Fix integer overflow in transmit_midi_msg()
Greg Kroah-Hartman (1):
Linux 4.19.169
Jan Kara (2):
bfq: Fix computation of shallow depth
ext4: fix superblock checksum failure when setting password salt
Jann Horn (1):
mm, slub: consider rest of partial list if acquire_slab() fails
Jerome Brunet (1):
ASoC: meson: axg-tdm-interface: fix loopback
Jesper Dangaard Brouer (1):
netfilter: conntrack: fix reading nf_conntrack_buckets
Leon Schuermann (1):
r8152: Add Lenovo Powered USB-C Travel Hub
Mark Bloch (1):
RDMA/mlx5: Fix wrong free of blue flame register on error
Masahiro Yamada (3):
ARC: build: remove non-existing bootpImage from KBUILD_IMAGE
ARC: build: add uImage.lzma to the top-level target
ARC: build: add boot_targets to PHONY
Masami Hiramatsu (1):
tracing/kprobes: Do the notrace functions check without kprobes on
ftrace
Miaohe Lin (1):
mm/hugetlb: fix potential missing huge page size info
Michael Ellerman (1):
net: ethernet: fs_enet: Add missing MODULE_LICENSE
Mike Snitzer (1):
dm: eliminate potential source of excessive kernel log noise
Mikulas Patocka (1):
dm integrity: fix the maximum number of arguments
Olaf Hering (1):
kbuild: enforce -Werror=return-type
Paul Cercueil (1):
MIPS: boot: Fix unaligned access with CONFIG_MIPS_RAW_APPENDED_DTB
Randy Dunlap (1):
arch/arc: add copy_user_page() to <asm/page.h> to fix build error on
ARC
Rasmus Villemoes (1):
ethernet: ucc_geth: fix definition and size of ucc_geth_tx_global_pram
Roberto Sassu (1):
ima: Remove __init annotation from ima_pcrread()
Shawn Guo (1):
ACPI: scan: add stub acpi_create_platform_device() for !CONFIG_ACPI
Thomas Hebb (1):
ASoC: dapm: remove widget from dirty list on free
Trond Myklebust (3):
pNFS: Mark layout for return if return-on-close was not sent
NFS/pNFS: Fix a leak of the layout 'plh_outstanding' counter
NFS: nfs_igrab_and_active must first reference the superblock
Wei Liu (1):
x86/hyperv: check cpu mask after interrupt has been disabled
Yang Yingliang (1):
config: set config CONFIG_KPROBE_EVENTS_ON_NOTRACE default value
j.nixdorf(a)avm.de (1):
net: sunrpc: interpret the return value of kstrtou32 correctly
Makefile | 4 ++--
arch/arc/Makefile | 9 ++-----
arch/arc/include/asm/page.h | 1 +
arch/arm/boot/dts/picoxcell-pc3x2.dtsi | 4 ++++
arch/arm64/configs/hulk_defconfig | 1 +
arch/mips/boot/compressed/decompress.c | 3 ++-
arch/mips/kernel/relocate.c | 10 ++++++--
arch/x86/hyperv/mmu.c | 12 +++++++---
block/bfq-iosched.c | 8 +++----
drivers/acpi/internal.h | 2 +-
drivers/acpi/scan.c | 15 +++++++++++-
drivers/gpu/drm/msm/msm_drv.c | 8 +++----
drivers/infiniband/hw/mlx5/main.c | 2 +-
drivers/infiniband/hw/usnic/usnic_ib_verbs.c | 3 +++
drivers/isdn/mISDN/Kconfig | 1 +
drivers/md/dm-integrity.c | 2 +-
drivers/md/dm-snap.c | 24 +++++++++++++++++++
drivers/md/dm.c | 2 +-
.../ethernet/freescale/fs_enet/mii-bitbang.c | 1 +
.../net/ethernet/freescale/fs_enet/mii-fec.c | 1 +
drivers/net/ethernet/freescale/ucc_geth.h | 9 ++++++-
drivers/net/usb/cdc_ether.c | 7 ++++++
drivers/net/usb/r8152.c | 1 +
fs/btrfs/qgroup.c | 13 +++++++---
fs/btrfs/super.c | 8 +++++++
fs/ext4/ioctl.c | 3 +++
fs/nfs/internal.h | 12 ++++++----
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/pnfs.c | 7 ++++++
include/linux/acpi.h | 7 ++++++
kernel/trace/Kconfig | 2 +-
kernel/trace/trace_kprobe.c | 2 +-
mm/hugetlb.c | 2 +-
mm/slub.c | 2 +-
net/netfilter/nf_conntrack_standalone.c | 3 +++
net/netfilter/nf_nat_core.c | 1 +
net/sunrpc/addr.c | 2 +-
security/integrity/ima/ima_crypto.c | 2 +-
security/lsm_audit.c | 7 ++++--
sound/firewire/fireface/ff-transaction.c | 2 +-
sound/firewire/tascam/tascam-transaction.c | 2 +-
sound/soc/intel/skylake/cnl-sst.c | 1 +
sound/soc/meson/axg-tdm-interface.c | 14 ++++++++++-
sound/soc/soc-dapm.c | 1 +
44 files changed, 176 insertions(+), 49 deletions(-)
--
2.25.1
1
43
27 Jan '21
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
MAP_CHECKNODE was defined in uapi/asm-generic/mman.h, that was not
automatically included by mm/mmap.c when building on platforms such as
mips, and result in following compiling error:
mm/mmap.c: In function ‘__do_mmap’:
mm/mmap.c:1581:14: error: ‘MAP_CHECKNODE’ undeclared (first use in this function)
if (flags & MAP_CHECKNODE)
^
mm/mmap.c:1581:14: note: each undeclared identifier is reported only once for each function it appears in
scripts/Makefile.build:303: recipe for target 'mm/mmap.o' failed
Fixes: 56a22a261008 ("arm64/ascend: mm: Add MAP_CHECKNODE flag to check node hugetlb")
Signed-off-by: Bixuan Cui <cuibixuan(a)huawei.com>
---
arch/alpha/include/uapi/asm/mman.h | 1 +
arch/mips/include/uapi/asm/mman.h | 1 +
arch/parisc/include/uapi/asm/mman.h | 1 +
arch/powerpc/include/uapi/asm/mman.h | 1 +
arch/sparc/include/uapi/asm/mman.h | 1 +
arch/xtensa/include/uapi/asm/mman.h | 1 +
6 files changed, 6 insertions(+)
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index b3acfc00..1c7ce27 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -34,6 +34,7 @@
#define MAP_HUGETLB 0x100000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x200000/* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_SYNC 2 /* synchronous memory sync */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 72a00c7..4570a54 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -52,6 +52,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
/*
* Flags for msync
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 9e989d6..06857eb 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -28,6 +28,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#define MS_SYNC 1 /* synchronous memory sync */
#define MS_ASYNC 2 /* sync memory asynchronously */
diff --git a/arch/powerpc/include/uapi/asm/mman.h b/arch/powerpc/include/uapi/asm/mman.h
index 95f884a..24354f7 100644
--- a/arch/powerpc/include/uapi/asm/mman.h
+++ b/arch/powerpc/include/uapi/asm/mman.h
@@ -30,6 +30,7 @@
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
/* Override any generic PKEY permission defines */
#define PKEY_DISABLE_EXECUTE 0x4
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
index 0d1881b..214abe1 100644
--- a/arch/sparc/include/uapi/asm/mman.h
+++ b/arch/sparc/include/uapi/asm/mman.h
@@ -27,6 +27,7 @@
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#endif /* _UAPI__SPARC_MMAN_H__ */
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index f584a59..2c9d705 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -59,6 +59,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
* uninitialized */
--
2.7.4
1
0
From: zhoukang <zhoukang7(a)huawei.com>
euleros inclusion
category: bugfix
bugzilla: 46918
--------------------------------
EulerOS is compatible with openEuler KABI, use the same config;
So arch/arm64/configs/euleros_defconfig file is no longer used;
Signed-off-by: zhoukang <zhoukang7(a)huawei.com>
Acked-by: Xie XiuQi <xiexiuqi(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/arm64/configs/euleros_defconfig | 5680 --------------------------
1 file changed, 5680 deletions(-)
delete mode 100644 arch/arm64/configs/euleros_defconfig
diff --git a/arch/arm64/configs/euleros_defconfig b/arch/arm64/configs/euleros_defconfig
deleted file mode 100644
index 53af3aa696386..0000000000000
--- a/arch/arm64/configs/euleros_defconfig
+++ /dev/null
@@ -1,5680 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 4.19.30 Kernel Configuration
-#
-
-#
-# Compiler: gcc (GCC) 7.3.0
-#
-CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=70300
-CONFIG_CLANG_VERSION=0
-CONFIG_IRQ_WORK=y
-CONFIG_BUILDTIME_EXTABLE_SORT=y
-CONFIG_THREAD_INFO_IN_TASK=y
-
-#
-# General setup
-#
-CONFIG_INIT_ENV_ARG_LIMIT=32
-# CONFIG_COMPILE_TEST is not set
-CONFIG_LOCALVERSION=""
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_BUILD_SALT=""
-CONFIG_DEFAULT_HOSTNAME="(none)"
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_POSIX_MQUEUE_SYSCTL=y
-CONFIG_CROSS_MEMORY_ATTACH=y
-# CONFIG_USELIB is not set
-CONFIG_AUDIT=y
-CONFIG_HAVE_ARCH_AUDITSYSCALL=y
-CONFIG_AUDITSYSCALL=y
-CONFIG_AUDIT_WATCH=y
-CONFIG_AUDIT_TREE=y
-
-#
-# IRQ subsystem
-#
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
-CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
-CONFIG_GENERIC_IRQ_MIGRATION=y
-CONFIG_HARDIRQS_SW_RESEND=y
-CONFIG_IRQ_DOMAIN=y
-CONFIG_IRQ_DOMAIN_HIERARCHY=y
-CONFIG_GENERIC_MSI_IRQ=y
-CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
-CONFIG_HANDLE_DOMAIN_IRQ=y
-CONFIG_IRQ_FORCED_THREADING=y
-CONFIG_SPARSE_IRQ=y
-# CONFIG_GENERIC_IRQ_DEBUGFS is not set
-CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
-CONFIG_ARCH_CLOCKSOURCE_DATA=y
-CONFIG_GENERIC_TIME_VSYSCALL=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_ARCH_HAS_TICK_BROADCAST=y
-CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
-
-#
-# Timers subsystem
-#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ_COMMON=y
-# CONFIG_HZ_PERIODIC is not set
-# CONFIG_NO_HZ_IDLE is not set
-CONFIG_NO_HZ_FULL=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
-
-#
-# CPU/Task time and stats accounting
-#
-CONFIG_VIRT_CPU_ACCOUNTING=y
-CONFIG_VIRT_CPU_ACCOUNTING_GEN=y
-CONFIG_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_SCHED_AVG_IRQ=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_TASKSTATS=y
-CONFIG_TASK_DELAY_ACCT=y
-CONFIG_TASK_XACCT=y
-CONFIG_TASK_IO_ACCOUNTING=y
-CONFIG_CPU_ISOLATION=y
-
-#
-# RCU Subsystem
-#
-CONFIG_TREE_RCU=y
-# CONFIG_RCU_EXPERT is not set
-CONFIG_SRCU=y
-CONFIG_TREE_SRCU=y
-CONFIG_RCU_STALL_COMMON=y
-CONFIG_RCU_NEED_SEGCBLIST=y
-CONFIG_CONTEXT_TRACKING=y
-# CONFIG_CONTEXT_TRACKING_FORCE is not set
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_BUILD_BIN2C=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=20
-CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
-CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
-CONFIG_GENERIC_SCHED_CLOCK=y
-CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
-CONFIG_ARCH_SUPPORTS_INT128=y
-CONFIG_NUMA_BALANCING=y
-CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
-CONFIG_CGROUPS=y
-CONFIG_PAGE_COUNTER=y
-CONFIG_MEMCG=y
-CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_SWAP_ENABLED=y
-CONFIG_MEMCG_KMEM=y
-CONFIG_BLK_CGROUP=y
-# CONFIG_DEBUG_BLK_CGROUP is not set
-CONFIG_CGROUP_WRITEBACK=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_RDMA=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_HUGETLB=y
-CONFIG_CPUSETS=y
-CONFIG_PROC_PID_CPUSET=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CGROUP_CPUACCT=y
-CONFIG_CGROUP_PERF=y
-CONFIG_CGROUP_BPF=y
-# CONFIG_CGROUP_DEBUG is not set
-CONFIG_SOCK_CGROUP_DATA=y
-CONFIG_CGROUP_FILES=y
-CONFIG_NAMESPACES=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
-CONFIG_USER_NS=y
-CONFIG_PID_NS=y
-CONFIG_NET_NS=y
-CONFIG_CHECKPOINT_RESTORE=y
-CONFIG_SCHED_STEAL=y
-CONFIG_SCHED_AUTOGROUP=y
-# CONFIG_SYSFS_DEPRECATED is not set
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_RD_GZIP=y
-CONFIG_RD_BZIP2=y
-CONFIG_RD_LZMA=y
-CONFIG_RD_XZ=y
-CONFIG_RD_LZO=y
-CONFIG_RD_LZ4=y
-CONFIG_INITRAMFS_FILE_METADATA=""
-CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_ANON_INODES=y
-CONFIG_HAVE_UID16=y
-CONFIG_SYSCTL_EXCEPTION_TRACE=y
-CONFIG_BPF=y
-CONFIG_EXPERT=y
-CONFIG_UID16=y
-CONFIG_MULTIUSER=y
-# CONFIG_SGETMASK_SYSCALL is not set
-CONFIG_SYSFS_SYSCALL=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_FHANDLE=y
-CONFIG_POSIX_TIMERS=y
-CONFIG_PRINTK=y
-CONFIG_PRINTK_NMI=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_FUTEX_PI=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_AIO=y
-CONFIG_ADVISE_SYSCALLS=y
-CONFIG_MEMBARRIER=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_BASE_RELATIVE=y
-CONFIG_BPF_SYSCALL=y
-CONFIG_BPF_JIT_ALWAYS_ON=y
-CONFIG_USERFAULTFD=y
-CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
-CONFIG_RSEQ=y
-# CONFIG_DEBUG_RSEQ is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_PERF_USE_VMALLOC=y
-# CONFIG_PC104 is not set
-
-#
-# Kernel Performance Events And Counters
-#
-CONFIG_PERF_EVENTS=y
-CONFIG_DEBUG_PERF_USE_VMALLOC=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLUB_DEBUG=y
-# CONFIG_SLUB_MEMCG_SYSFS_ON is not set
-# CONFIG_COMPAT_BRK is not set
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-# CONFIG_SLOB is not set
-CONFIG_SLAB_MERGE_DEFAULT=y
-CONFIG_SLAB_FREELIST_RANDOM=y
-# CONFIG_SLAB_FREELIST_HARDENED is not set
-CONFIG_SLUB_CPU_PARTIAL=y
-CONFIG_SYSTEM_DATA_VERIFICATION=y
-CONFIG_PROFILING=y
-CONFIG_TRACEPOINTS=y
-CONFIG_ARM64=y
-CONFIG_64BIT=y
-CONFIG_MMU=y
-CONFIG_ARM64_PAGE_SHIFT=12
-CONFIG_ARM64_CONT_SHIFT=4
-CONFIG_ARCH_MMAP_RND_BITS_MIN=18
-CONFIG_ARCH_MMAP_RND_BITS_MAX=33
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CSUM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ZONE_DMA32=y
-CONFIG_HAVE_GENERIC_GUP=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_SMP=y
-CONFIG_KERNEL_MODE_NEON=y
-CONFIG_FIX_EARLYCON_MEM=y
-CONFIG_PGTABLE_LEVELS=4
-CONFIG_ARCH_SUPPORTS_UPROBES=y
-CONFIG_ARCH_PROC_KCORE_TEXT=y
-
-#
-# Platform selection
-#
-# CONFIG_ARCH_ACTIONS is not set
-# CONFIG_ARCH_SUNXI is not set
-# CONFIG_ARCH_ALPINE is not set
-# CONFIG_ARCH_BCM2835 is not set
-# CONFIG_ARCH_BCM_IPROC is not set
-# CONFIG_ARCH_BERLIN is not set
-# CONFIG_ARCH_BRCMSTB is not set
-# CONFIG_ARCH_EXYNOS is not set
-# CONFIG_ARCH_K3 is not set
-# CONFIG_ARCH_LAYERSCAPE is not set
-# CONFIG_ARCH_LG1K is not set
-CONFIG_ARCH_HISI=y
-# CONFIG_ARCH_MEDIATEK is not set
-# CONFIG_ARCH_MESON is not set
-# CONFIG_ARCH_MVEBU is not set
-CONFIG_ARCH_QCOM=y
-# CONFIG_ARCH_REALTEK is not set
-# CONFIG_ARCH_ROCKCHIP is not set
-CONFIG_ARCH_SEATTLE=y
-# CONFIG_ARCH_SYNQUACER is not set
-# CONFIG_ARCH_RENESAS is not set
-# CONFIG_ARCH_STRATIX10 is not set
-# CONFIG_ARCH_TEGRA is not set
-# CONFIG_ARCH_SPRD is not set
-CONFIG_ARCH_THUNDER=y
-CONFIG_ARCH_THUNDER2=y
-# CONFIG_ARCH_UNIPHIER is not set
-CONFIG_ARCH_VEXPRESS=y
-CONFIG_ARCH_XGENE=y
-# CONFIG_ARCH_ZX is not set
-# CONFIG_ARCH_ZYNQMP is not set
-CONFIG_HAVE_LIVEPATCH_WO_FTRACE=y
-
-#
-# Enable Livepatch
-#
-CONFIG_LIVEPATCH=y
-CONFIG_LIVEPATCH_WO_FTRACE=y
-CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY=y
-# CONFIG_LIVEPATCH_STACK is not set
-CONFIG_LIVEPATCH_RESTRICT_KPROBE=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_DOMAINS_GENERIC=y
-CONFIG_PCI_SYSCALL=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_HOTPLUG_PCI_PCIE=y
-CONFIG_PCIEAER=y
-CONFIG_PCIEAER_INJECT=m
-CONFIG_PCIE_ECRC=y
-CONFIG_PCIEASPM=y
-# CONFIG_PCIEASPM_DEBUG is not set
-CONFIG_PCIEASPM_DEFAULT=y
-# CONFIG_PCIEASPM_POWERSAVE is not set
-# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
-# CONFIG_PCIEASPM_PERFORMANCE is not set
-CONFIG_PCIE_PME=y
-CONFIG_PCIE_DPC=y
-# CONFIG_PCIE_PTM is not set
-CONFIG_PCI_MSI=y
-CONFIG_PCI_MSI_IRQ_DOMAIN=y
-CONFIG_PCI_QUIRKS=y
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
-CONFIG_PCI_STUB=y
-# CONFIG_PCI_PF_STUB is not set
-CONFIG_PCI_ATS=y
-CONFIG_PCI_ECAM=y
-CONFIG_PCI_IOV=y
-CONFIG_PCI_PRI=y
-CONFIG_PCI_PASID=y
-CONFIG_PCI_LABEL=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=y
-CONFIG_HOTPLUG_PCI_ACPI_IBM=m
-# CONFIG_HOTPLUG_PCI_CPCI is not set
-CONFIG_HOTPLUG_PCI_SHPC=y
-
-#
-# PCI controller drivers
-#
-
-#
-# Cadence PCIe controllers support
-#
-# CONFIG_PCIE_CADENCE_HOST is not set
-# CONFIG_PCI_FTPCI100 is not set
-CONFIG_PCI_HOST_COMMON=y
-CONFIG_PCI_HOST_GENERIC=y
-# CONFIG_PCIE_XILINX is not set
-CONFIG_PCI_XGENE=y
-CONFIG_PCI_XGENE_MSI=y
-CONFIG_PCI_HOST_THUNDER_PEM=y
-CONFIG_PCI_HOST_THUNDER_ECAM=y
-
-#
-# DesignWare PCI Core Support
-#
-CONFIG_PCIE_DW=y
-CONFIG_PCIE_DW_HOST=y
-# CONFIG_PCIE_DW_PLAT_HOST is not set
-CONFIG_PCI_HISI=y
-# CONFIG_PCIE_QCOM is not set
-# CONFIG_PCIE_KIRIN is not set
-# CONFIG_PCIE_HISI_STB is not set
-
-#
-# PCI Endpoint
-#
-# CONFIG_PCI_ENDPOINT is not set
-
-#
-# PCI switch controller drivers
-#
-# CONFIG_PCI_SW_SWITCHTEC is not set
-
-#
-# Kernel Features
-#
-
-#
-# ARM errata workarounds via the alternatives framework
-#
-CONFIG_ARM64_ERRATUM_826319=y
-CONFIG_ARM64_ERRATUM_827319=y
-CONFIG_ARM64_ERRATUM_824069=y
-CONFIG_ARM64_ERRATUM_819472=y
-CONFIG_ARM64_ERRATUM_832075=y
-CONFIG_ARM64_ERRATUM_834220=y
-CONFIG_ARM64_ERRATUM_845719=y
-CONFIG_ARM64_ERRATUM_843419=y
-CONFIG_ARM64_ERRATUM_1024718=y
-# CONFIG_ARM64_ERRATUM_1463225 is not set
-# CONFIG_ARM64_ERRATUM_1542419 is not set
-CONFIG_CAVIUM_ERRATUM_22375=y
-CONFIG_CAVIUM_ERRATUM_23144=y
-CONFIG_CAVIUM_ERRATUM_23154=y
-CONFIG_CAVIUM_ERRATUM_27456=y
-CONFIG_CAVIUM_ERRATUM_30115=y
-CONFIG_QCOM_FALKOR_ERRATUM_1003=y
-CONFIG_QCOM_FALKOR_ERRATUM_1009=y
-CONFIG_QCOM_QDF2400_ERRATUM_0065=y
-CONFIG_SOCIONEXT_SYNQUACER_PREITS=y
-CONFIG_HISILICON_ERRATUM_161600802=y
-CONFIG_QCOM_FALKOR_ERRATUM_E1041=y
-CONFIG_ARM64_4K_PAGES=y
-# CONFIG_ARM64_16K_PAGES is not set
-# CONFIG_ARM64_64K_PAGES is not set
-# CONFIG_ARM64_VA_BITS_39 is not set
-CONFIG_ARM64_VA_BITS_48=y
-CONFIG_ARM64_VA_BITS=48
-CONFIG_ARM64_PA_BITS_48=y
-CONFIG_ARM64_PA_BITS=48
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_SCHED_MC=y
-# CONFIG_SCHED_SMT is not set
-CONFIG_NR_CPUS=1024
-CONFIG_HOTPLUG_CPU=y
-CONFIG_ARM64_ERR_RECOV=y
-CONFIG_MPAM=y
-CONFIG_NUMA=y
-CONFIG_NODES_SHIFT=3
-CONFIG_NUMA_AWARE_SPINLOCKS=y
-CONFIG_USE_PERCPU_NUMA_NODE_ID=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
-CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
-CONFIG_HOLES_IN_ZONE=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_SCHED_HRTICK=y
-CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
-CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_DEFAULT=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_HAVE_ARCH_PFN_VALID=y
-CONFIG_HW_PERF_EVENTS=y
-CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_SECCOMP=y
-CONFIG_PARAVIRT=y
-CONFIG_PARAVIRT_SPINLOCKS=y
-CONFIG_PARAVIRT_TIME_ACCOUNTING=y
-CONFIG_KEXEC=y
-CONFIG_CRASH_DUMP=y
-# CONFIG_XEN is not set
-CONFIG_FORCE_MAX_ZONEORDER=11
-CONFIG_UNMAP_KERNEL_AT_EL0=y
-CONFIG_HARDEN_BRANCH_PREDICTOR=y
-CONFIG_HARDEN_EL2_VECTORS=y
-CONFIG_ARM64_SSBD=y
-# CONFIG_ARMV8_DEPRECATED is not set
-# CONFIG_ARM64_SW_TTBR0_PAN is not set
-
-#
-# ARMv8.1 architectural features
-#
-CONFIG_ARM64_HW_AFDBM=y
-CONFIG_ARM64_PAN=y
-CONFIG_ARM64_LSE_ATOMICS=y
-CONFIG_ARM64_VHE=y
-
-#
-# ARMv8.2 architectural features
-#
-CONFIG_ARM64_UAO=y
-CONFIG_ARM64_PMEM=y
-CONFIG_ARM64_RAS_EXTN=y
-CONFIG_ARM64_SVE=y
-CONFIG_ARM64_MODULE_PLTS=y
-CONFIG_ARM64_PSEUDO_NMI=y
-CONFIG_RELOCATABLE=y
-CONFIG_RANDOMIZE_BASE=y
-CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
-CONFIG_ARM64_CNP=n
-
-#
-# ARMv8.4 architectural features
-#
-# CONFIG_ARM64_TLB_RANGE is not set
-
-#
-# ARMv8.5 architectural features
-#
-# CONFIG_ARCH_RANDOM is not set
-# CONFIG_ARM64_E0PD is not set
-
-#
-# Boot options
-#
-CONFIG_ARM64_ACPI_PARKING_PROTOCOL=y
-CONFIG_CMDLINE="console=ttyAMA0"
-# CONFIG_CMDLINE_FORCE is not set
-CONFIG_EFI_STUB=y
-CONFIG_EFI=y
-CONFIG_DMI=y
-CONFIG_COMPAT=y
-CONFIG_SYSVIPC_COMPAT=y
-
-#
-# Power management options
-#
-CONFIG_SUSPEND=y
-CONFIG_SUSPEND_FREEZER=y
-# CONFIG_SUSPEND_SKIP_SYNC is not set
-CONFIG_HIBERNATE_CALLBACKS=y
-CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION=""
-CONFIG_PM_SLEEP=y
-CONFIG_PM_SLEEP_SMP=y
-# CONFIG_PM_AUTOSLEEP is not set
-# CONFIG_PM_WAKELOCKS is not set
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-# CONFIG_PM_ADVANCED_DEBUG is not set
-# CONFIG_PM_TEST_SUSPEND is not set
-CONFIG_PM_SLEEP_DEBUG=y
-# CONFIG_DPM_WATCHDOG is not set
-CONFIG_PM_CLK=y
-CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
-CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
-CONFIG_PM_GENERIC_DOMAINS_OF=y
-CONFIG_CPU_PM=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_HIBERNATION_HEADER=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# CPU Power Management
-#
-
-#
-# CPU Idle
-#
-CONFIG_CPU_IDLE=y
-# CONFIG_CPU_IDLE_GOV_LADDER is not set
-CONFIG_CPU_IDLE_GOV_MENU=y
-# CONFIG_CPU_IDLE_GOV_TEO is not set
-# CONFIG_CPU_IDLE_GOV_HALTPOLL is not set
-
-#
-# ARM CPU Idle Drivers
-#
-# CONFIG_ARM_CPUIDLE is not set
-# CONFIG_HALTPOLL_CPUIDLE is not set
-
-#
-# CPU Frequency scaling
-#
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_GOV_ATTR_SET=y
-CONFIG_CPU_FREQ_GOV_COMMON=y
-CONFIG_CPU_FREQ_STAT=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set
-
-#
-# CPU frequency scaling drivers
-#
-# CONFIG_CPUFREQ_DT is not set
-CONFIG_ACPI_CPPC_CPUFREQ=y
-CONFIG_HISILICON_CPPC_CPUFREQ_WORKAROUND=y
-# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set
-CONFIG_ARM_SCPI_CPUFREQ=m
-# CONFIG_QORIQ_CPUFREQ is not set
-
-#
-# Firmware Drivers
-#
-CONFIG_ARM_PSCI_FW=y
-# CONFIG_ARM_PSCI_CHECKER is not set
-# CONFIG_ARM_SCMI_PROTOCOL is not set
-CONFIG_ARM_SCPI_PROTOCOL=m
-CONFIG_ARM_SCPI_POWER_DOMAIN=m
-CONFIG_ARM_SDE_INTERFACE=y
-# CONFIG_FIRMWARE_MEMMAP is not set
-CONFIG_DMIID=y
-CONFIG_DMI_SYSFS=y
-CONFIG_FW_CFG_SYSFS=y
-# CONFIG_FW_CFG_SYSFS_CMDLINE is not set
-CONFIG_HAVE_ARM_SMCCC=y
-# CONFIG_GOOGLE_FIRMWARE is not set
-
-#
-# EFI (Extensible Firmware Interface) Support
-#
-CONFIG_EFI_VARS=y
-CONFIG_EFI_ESRT=y
-CONFIG_EFI_VARS_PSTORE=y
-CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y
-CONFIG_EFI_PARAMS_FROM_FDT=y
-CONFIG_EFI_RUNTIME_WRAPPERS=y
-CONFIG_EFI_ARMSTUB=y
-CONFIG_EFI_ARMSTUB_DTB_LOADER=y
-# CONFIG_EFI_BOOTLOADER_CONTROL is not set
-# CONFIG_EFI_CAPSULE_LOADER is not set
-# CONFIG_EFI_TEST is not set
-# CONFIG_RESET_ATTACK_MITIGATION is not set
-CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
-CONFIG_UEFI_CPER=y
-CONFIG_UEFI_CPER_ARM=y
-
-#
-# Tegra firmware driver
-#
-CONFIG_ARCH_SUPPORTS_ACPI=y
-CONFIG_ACPI=y
-CONFIG_ACPI_GENERIC_GSI=y
-CONFIG_ACPI_CCA_REQUIRED=y
-# CONFIG_ACPI_DEBUGGER is not set
-CONFIG_ACPI_SPCR_TABLE=y
-# CONFIG_ACPI_EC_DEBUGFS is not set
-CONFIG_ACPI_BUTTON=y
-CONFIG_ACPI_FAN=y
-# CONFIG_ACPI_TAD is not set
-# CONFIG_ACPI_DOCK is not set
-CONFIG_ACPI_PROCESSOR_IDLE=y
-CONFIG_ACPI_MCFG=y
-CONFIG_ACPI_CPPC_LIB=y
-CONFIG_ACPI_PROCESSOR=y
-CONFIG_ACPI_IPMI=m
-CONFIG_ACPI_HOTPLUG_CPU=y
-CONFIG_ACPI_THERMAL=y
-CONFIG_ACPI_NUMA=y
-CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
-CONFIG_ACPI_TABLE_UPGRADE=y
-# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_PCI_SLOT=y
-CONFIG_ACPI_CONTAINER=y
-# CONFIG_ACPI_HOTPLUG_MEMORY is not set
-CONFIG_ACPI_HED=y
-# CONFIG_ACPI_CUSTOM_METHOD is not set
-# CONFIG_ACPI_BGRT is not set
-CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y
-# CONFIG_ACPI_NFIT is not set
-CONFIG_HAVE_ACPI_APEI=y
-CONFIG_ACPI_APEI=y
-CONFIG_ACPI_APEI_GHES=y
-CONFIG_ACPI_APEI_PCIEAER=y
-CONFIG_ACPI_APEI_SEA=y
-CONFIG_ACPI_APEI_MEMORY_FAILURE=y
-CONFIG_ACPI_APEI_EINJ=m
-# CONFIG_ACPI_APEI_ERST_DEBUG is not set
-# CONFIG_PMIC_OPREGION is not set
-# CONFIG_ACPI_CONFIGFS is not set
-CONFIG_ACPI_IORT=y
-CONFIG_ACPI_GTDT=y
-CONFIG_ACPI_PPTT=y
-CONFIG_HAVE_KVM_IRQCHIP=y
-CONFIG_HAVE_KVM_IRQFD=y
-CONFIG_HAVE_KVM_IRQ_ROUTING=y
-CONFIG_HAVE_KVM_EVENTFD=y
-CONFIG_KVM_MMIO=y
-CONFIG_HAVE_KVM_MSI=y
-CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
-CONFIG_KVM_VFIO=y
-CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y
-CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
-CONFIG_HAVE_KVM_IRQ_BYPASS=y
-CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y
-CONFIG_IRQ_BYPASS_MANAGER=y
-CONFIG_VIRTUALIZATION=y
-CONFIG_KVM=y
-CONFIG_KVM_ARM_HOST=y
-CONFIG_KVM_ARM_PMU=y
-CONFIG_KVM_INDIRECT_VECTORS=y
-CONFIG_VHOST_NET=m
-# CONFIG_VHOST_SCSI is not set
-CONFIG_VHOST_VSOCK=m
-CONFIG_VHOST=m
-# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
-CONFIG_ARM64_CRYPTO=y
-CONFIG_CRYPTO_SHA256_ARM64=m
-# CONFIG_CRYPTO_SHA512_ARM64 is not set
-CONFIG_CRYPTO_SHA1_ARM64_CE=m
-CONFIG_CRYPTO_SHA2_ARM64_CE=m
-# CONFIG_CRYPTO_SHA512_ARM64_CE is not set
-# CONFIG_CRYPTO_SHA3_ARM64 is not set
-# CONFIG_CRYPTO_SM3_ARM64_CE is not set
-CONFIG_CRYPTO_SM4_ARM64_CE=m
-CONFIG_CRYPTO_GHASH_ARM64_CE=m
-# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set
-CONFIG_CRYPTO_CRC32_ARM64_CE=m
-CONFIG_CRYPTO_AES_ARM64=y
-CONFIG_CRYPTO_AES_ARM64_CE=m
-CONFIG_CRYPTO_AES_ARM64_CE_CCM=m
-CONFIG_CRYPTO_AES_ARM64_CE_BLK=m
-CONFIG_CRYPTO_AES_ARM64_NEON_BLK=m
-# CONFIG_CRYPTO_CHACHA20_NEON is not set
-# CONFIG_CRYPTO_AES_ARM64_BS is not set
-
-#
-# General architecture-dependent options
-#
-CONFIG_CRASH_CORE=y
-CONFIG_KEXEC_CORE=y
-CONFIG_OPROFILE_NMI_TIMER=y
-CONFIG_KPROBES=y
-CONFIG_JUMP_LABEL=y
-CONFIG_STATIC_KEYS_SELFTEST=y
-CONFIG_UPROBES=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_KRETPROBES=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_NMI=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_GENERIC_SMP_IDLE_THREAD=y
-CONFIG_GENERIC_IDLE_POLL_SETUP=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_HW_BREAKPOINT=y
-CONFIG_HAVE_PERF_EVENTS_NMI=y
-CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_RCU_TABLE_FREE=y
-CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
-CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
-CONFIG_HAVE_CMPXCHG_LOCAL=y
-CONFIG_HAVE_CMPXCHG_DOUBLE=y
-CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
-CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
-CONFIG_SECCOMP_FILTER=y
-CONFIG_HAVE_STACKPROTECTOR=y
-CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
-CONFIG_STACKPROTECTOR=y
-CONFIG_STACKPROTECTOR_STRONG=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARCH_HUGE_VMAP=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_MODULES_USE_ELF_RELA=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
-CONFIG_ARCH_MMAP_RND_BITS=18
-CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11
-CONFIG_CLONE_BACKWARDS=y
-CONFIG_OLD_SIGSUSPEND3=y
-CONFIG_COMPAT_OLD_SIGACTION=y
-CONFIG_COMPAT_32BIT_TIME=y
-CONFIG_HAVE_ARCH_VMAP_STACK=y
-# CONFIG_VMAP_STACK is not set
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
-
-#
-# GCOV-based kernel profiling
-#
-# CONFIG_GCOV_KERNEL is not set
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_PLUGIN_HOSTCC=""
-CONFIG_HAVE_GCC_PLUGINS=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-CONFIG_MODULE_FORCE_LOAD=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_MODULE_SIG=y
-# CONFIG_MODULE_SIG_FORCE is not set
-CONFIG_MODULE_SIG_ALL=y
-# CONFIG_MODULE_SIG_SHA1 is not set
-# CONFIG_MODULE_SIG_SHA224 is not set
-CONFIG_MODULE_SIG_SHA256=y
-# CONFIG_MODULE_SIG_SHA384 is not set
-# CONFIG_MODULE_SIG_SHA512 is not set
-CONFIG_MODULE_SIG_HASH="sha256"
-# CONFIG_MODULE_COMPRESS is not set
-# CONFIG_TRIM_UNUSED_KSYMS is not set
-CONFIG_MODULES_TREE_LOOKUP=y
-CONFIG_BLOCK=y
-CONFIG_BLK_SCSI_REQUEST=y
-CONFIG_BLK_DEV_BSG=y
-CONFIG_BLK_DEV_BSGLIB=y
-CONFIG_BLK_DEV_INTEGRITY=y
-CONFIG_BLK_DEV_ZONED=y
-CONFIG_BLK_DEV_THROTTLING=y
-# CONFIG_BLK_DEV_THROTTLING_LOW is not set
-# CONFIG_BLK_CMDLINE_PARSER is not set
-CONFIG_BLK_WBT=y
-# CONFIG_BLK_CGROUP_IOLATENCY is not set
-# CONFIG_BLK_WBT_SQ is not set
-# CONFIG_BLK_CGROUP_IOCOST is not set
-CONFIG_BLK_WBT_MQ=y
-CONFIG_BLK_DEBUG_FS=y
-CONFIG_BLK_DEBUG_FS_ZONED=y
-# CONFIG_BLK_SED_OPAL is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_AIX_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
-# CONFIG_SYSV68_PARTITION is not set
-# CONFIG_CMDLINE_PARTITION is not set
-CONFIG_BLOCK_COMPAT=y
-CONFIG_BLK_MQ_PCI=y
-CONFIG_BLK_MQ_VIRTIO=y
-CONFIG_BLK_MQ_RDMA=y
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-CONFIG_DEFAULT_DEADLINE=y
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="deadline"
-CONFIG_MQ_IOSCHED_DEADLINE=y
-CONFIG_MQ_IOSCHED_KYBER=y
-CONFIG_IOSCHED_BFQ=y
-CONFIG_BFQ_GROUP_IOSCHED=y
-CONFIG_PREEMPT_NOTIFIERS=y
-CONFIG_PADATA=y
-CONFIG_ASN1=y
-CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
-CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_LOCK=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_INLINE_READ_LOCK=y
-CONFIG_ARCH_INLINE_READ_LOCK_BH=y
-CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_READ_UNLOCK=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_INLINE_WRITE_LOCK=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_SPIN_TRYLOCK=y
-CONFIG_INLINE_SPIN_TRYLOCK_BH=y
-CONFIG_INLINE_SPIN_LOCK=y
-CONFIG_INLINE_SPIN_LOCK_BH=y
-CONFIG_INLINE_SPIN_LOCK_IRQ=y
-CONFIG_INLINE_SPIN_LOCK_IRQSAVE=y
-CONFIG_INLINE_SPIN_UNLOCK_BH=y
-CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
-CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_READ_LOCK=y
-CONFIG_INLINE_READ_LOCK_BH=y
-CONFIG_INLINE_READ_LOCK_IRQ=y
-CONFIG_INLINE_READ_LOCK_IRQSAVE=y
-CONFIG_INLINE_READ_UNLOCK=y
-CONFIG_INLINE_READ_UNLOCK_BH=y
-CONFIG_INLINE_READ_UNLOCK_IRQ=y
-CONFIG_INLINE_READ_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_WRITE_LOCK=y
-CONFIG_INLINE_WRITE_LOCK_BH=y
-CONFIG_INLINE_WRITE_LOCK_IRQ=y
-CONFIG_INLINE_WRITE_LOCK_IRQSAVE=y
-CONFIG_INLINE_WRITE_UNLOCK=y
-CONFIG_INLINE_WRITE_UNLOCK_BH=y
-CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
-CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_MUTEX_SPIN_ON_OWNER=y
-CONFIG_RWSEM_SPIN_ON_OWNER=y
-CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
-CONFIG_QUEUED_SPINLOCKS=y
-CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
-CONFIG_QUEUED_RWLOCKS=y
-CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
-CONFIG_FREEZER=y
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_COMPAT_BINFMT_ELF=y
-CONFIG_ELFCORE=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
-CONFIG_BINFMT_SCRIPT=y
-CONFIG_BINFMT_MISC=m
-CONFIG_COREDUMP=y
-
-#
-# Memory Management options
-#
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_NEED_MULTIPLE_NODES=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_EXTREME=y
-CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
-CONFIG_SPARSEMEM_VMEMMAP=y
-CONFIG_HAVE_MEMBLOCK=y
-CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
-CONFIG_NO_BOOTMEM=y
-CONFIG_MEMORY_ISOLATION=y
-CONFIG_MEMORY_HOTPLUG=y
-CONFIG_MEMORY_HOTPLUG_SPARSE=y
-# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MEMORY_BALLOON=y
-CONFIG_BALLOON_COMPACTION=y
-CONFIG_COMPACTION=y
-CONFIG_MIGRATION=y
-CONFIG_PHYS_ADDR_T_64BIT=y
-CONFIG_MMU_NOTIFIER=y
-CONFIG_KSM=y
-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
-CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
-CONFIG_MEMORY_FAILURE=y
-CONFIG_HWPOISON_INJECT=m
-CONFIG_TRANSPARENT_HUGEPAGE=y
-CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
-# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
-CONFIG_TRANSPARENT_HUGE_PAGECACHE=y
-CONFIG_CLEANCACHE=y
-CONFIG_FRONTSWAP=y
-CONFIG_SHRINK_PAGECACHE=y
-CONFIG_CMA=y
-# CONFIG_CMA_DEBUG is not set
-# CONFIG_CMA_DEBUGFS is not set
-CONFIG_CMA_AREAS=7
-CONFIG_ZSWAP=y
-CONFIG_ZPOOL=y
-CONFIG_ZBUD=y
-# CONFIG_Z3FOLD is not set
-CONFIG_ZSMALLOC=y
-# CONFIG_PGTABLE_MAPPING is not set
-CONFIG_ZSMALLOC_STAT=y
-CONFIG_GENERIC_EARLY_IOREMAP=y
-# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
-CONFIG_IDLE_PAGE_TRACKING=y
-# CONFIG_PERCPU_STATS is not set
-# CONFIG_GUP_BENCHMARK is not set
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
-CONFIG_NET=y
-CONFIG_COMPAT_NETLINK_MESSAGES=y
-CONFIG_NET_INGRESS=y
-CONFIG_NET_EGRESS=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_DIAG=m
-CONFIG_UNIX=y
-CONFIG_UNIX_DIAG=m
-CONFIG_TLS=m
-CONFIG_TLS_DEVICE=y
-CONFIG_XFRM=y
-CONFIG_XFRM_OFFLOAD=y
-CONFIG_XFRM_ALGO=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_INTERFACE is not set
-CONFIG_XFRM_SUB_POLICY=y
-CONFIG_XFRM_MIGRATE=y
-CONFIG_XFRM_STATISTICS=y
-CONFIG_XFRM_IPCOMP=m
-CONFIG_NET_KEY=m
-CONFIG_NET_KEY_MIGRATE=y
-# CONFIG_SMC is not set
-# CONFIG_XDP_SOCKETS is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_FIB_TRIE_STATS=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_CLASSID=y
-# CONFIG_IP_PNP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE_DEMUX=m
-CONFIG_NET_IP_TUNNEL=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE_COMMON=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_NET_IPVTI=m
-CONFIG_NET_UDP_TUNNEL=m
-# CONFIG_NET_FOU is not set
-# CONFIG_NET_FOU_IP_TUNNELS is not set
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_ESP_OFFLOAD=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_TUNNEL=m
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=m
-CONFIG_INET_TCP_DIAG=m
-CONFIG_INET_UDP_DIAG=m
-CONFIG_INET_RAW_DIAG=m
-# CONFIG_INET_DIAG_DESTROY is not set
-CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_TCP_CONG_BIC=m
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_TCP_CONG_WESTWOOD=m
-CONFIG_TCP_CONG_HTCP=m
-CONFIG_TCP_CONG_HSTCP=m
-CONFIG_TCP_CONG_HYBLA=m
-CONFIG_TCP_CONG_VEGAS=m
-CONFIG_TCP_CONG_NV=m
-CONFIG_TCP_CONG_SCALABLE=m
-CONFIG_TCP_CONG_LP=m
-CONFIG_TCP_CONG_VENO=m
-CONFIG_TCP_CONG_YEAH=m
-CONFIG_TCP_CONG_ILLINOIS=m
-CONFIG_TCP_CONG_DCTCP=m
-# CONFIG_TCP_CONG_CDG is not set
-CONFIG_TCP_CONG_BBR=m
-CONFIG_DEFAULT_CUBIC=y
-# CONFIG_DEFAULT_RENO is not set
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_ESP_OFFLOAD=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_MIP6=m
-# CONFIG_IPV6_ILA is not set
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_VTI=m
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_SIT_6RD=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_IPV6_TUNNEL=m
-CONFIG_IPV6_GRE=m
-CONFIG_IPV6_MULTIPLE_TABLES=y
-# CONFIG_IPV6_SUBTREES is not set
-CONFIG_IPV6_MROUTE=y
-CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
-CONFIG_IPV6_PIMSM_V2=y
-# CONFIG_IPV6_SEG6_LWTUNNEL is not set
-# CONFIG_IPV6_SEG6_HMAC is not set
-CONFIG_NETLABEL=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NET_PTP_CLASSIFY=y
-CONFIG_NETWORK_PHY_TIMESTAMPING=y
-CONFIG_NETFILTER=y
-CONFIG_NETFILTER_ADVANCED=y
-CONFIG_BRIDGE_NETFILTER=m
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_INGRESS=y
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_FAMILY_BRIDGE=y
-CONFIG_NETFILTER_FAMILY_ARP=y
-CONFIG_NETFILTER_NETLINK_ACCT=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NETFILTER_NETLINK_OSF=m
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_LOG_COMMON=m
-CONFIG_NF_LOG_NETDEV=m
-CONFIG_NETFILTER_CONNCOUNT=m
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_ZONES=y
-CONFIG_NF_CONNTRACK_PROCFS=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CONNTRACK_TIMEOUT=y
-CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CONNTRACK_LABELS=y
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-CONFIG_NF_CONNTRACK_BROADCAST=m
-CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-CONFIG_NF_CONNTRACK_SNMP=m
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NF_CT_NETLINK_TIMEOUT=m
-CONFIG_NF_CT_NETLINK_HELPER=m
-CONFIG_NETFILTER_NETLINK_GLUE_CT=y
-CONFIG_NF_NAT=m
-CONFIG_NF_NAT_NEEDED=y
-CONFIG_NF_NAT_PROTO_DCCP=y
-CONFIG_NF_NAT_PROTO_UDPLITE=y
-CONFIG_NF_NAT_PROTO_SCTP=y
-CONFIG_NF_NAT_AMANDA=m
-CONFIG_NF_NAT_FTP=m
-CONFIG_NF_NAT_IRC=m
-CONFIG_NF_NAT_SIP=m
-CONFIG_NF_NAT_TFTP=m
-CONFIG_NF_NAT_REDIRECT=y
-CONFIG_NETFILTER_SYNPROXY=m
-CONFIG_NF_TABLES=m
-CONFIG_NF_TABLES_SET=m
-CONFIG_NF_TABLES_INET=y
-CONFIG_NF_TABLES_NETDEV=y
-CONFIG_NFT_NUMGEN=m
-CONFIG_NFT_CT=m
-CONFIG_NFT_COUNTER=m
-# CONFIG_NFT_CONNLIMIT is not set
-CONFIG_NFT_LOG=m
-CONFIG_NFT_LIMIT=m
-CONFIG_NFT_MASQ=m
-CONFIG_NFT_REDIR=m
-CONFIG_NFT_NAT=m
-# CONFIG_NFT_TUNNEL is not set
-CONFIG_NFT_OBJREF=m
-CONFIG_NFT_QUEUE=m
-CONFIG_NFT_QUOTA=m
-CONFIG_NFT_REJECT=m
-CONFIG_NFT_REJECT_INET=m
-CONFIG_NFT_COMPAT=m
-CONFIG_NFT_HASH=m
-CONFIG_NFT_FIB=m
-CONFIG_NFT_FIB_INET=m
-# CONFIG_NFT_SOCKET is not set
-# CONFIG_NFT_OSF is not set
-# CONFIG_NFT_TPROXY is not set
-CONFIG_NF_DUP_NETDEV=m
-CONFIG_NFT_DUP_NETDEV=m
-CONFIG_NFT_FWD_NETDEV=m
-CONFIG_NFT_FIB_NETDEV=m
-# CONFIG_NF_FLOW_TABLE is not set
-CONFIG_NETFILTER_XTABLES=y
-
-#
-# Xtables combined modules
-#
-CONFIG_NETFILTER_XT_MARK=m
-CONFIG_NETFILTER_XT_CONNMARK=m
-CONFIG_NETFILTER_XT_SET=m
-
-#
-# Xtables targets
-#
-CONFIG_NETFILTER_XT_TARGET_AUDIT=m
-CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CT=m
-CONFIG_NETFILTER_XT_TARGET_DSCP=m
-CONFIG_NETFILTER_XT_TARGET_HL=m
-CONFIG_NETFILTER_XT_TARGET_HMARK=m
-CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
-CONFIG_NETFILTER_XT_TARGET_LED=m
-CONFIG_NETFILTER_XT_TARGET_LOG=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_NAT=m
-CONFIG_NETFILTER_XT_TARGET_NETMAP=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_TARGET_RATEEST=m
-CONFIG_NETFILTER_XT_TARGET_REDIRECT=m
-CONFIG_NETFILTER_XT_TARGET_TEE=m
-CONFIG_NETFILTER_XT_TARGET_TPROXY=m
-CONFIG_NETFILTER_XT_TARGET_TRACE=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
-
-#
-# Xtables matches
-#
-CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
-CONFIG_NETFILTER_XT_MATCH_BPF=m
-CONFIG_NETFILTER_XT_MATCH_CGROUP=m
-CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_CPU=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ECN=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_HL=m
-CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
-CONFIG_NETFILTER_XT_MATCH_IPVS=m
-CONFIG_NETFILTER_XT_MATCH_L2TP=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_NFACCT=m
-CONFIG_NETFILTER_XT_MATCH_OSF=m
-CONFIG_NETFILTER_XT_MATCH_OWNER=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_RATEEST=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_TIME=m
-CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_IP_SET=m
-CONFIG_IP_SET_MAX=256
-CONFIG_IP_SET_BITMAP_IP=m
-CONFIG_IP_SET_BITMAP_IPMAC=m
-CONFIG_IP_SET_BITMAP_PORT=m
-CONFIG_IP_SET_HASH_IP=m
-CONFIG_IP_SET_HASH_IPMARK=m
-CONFIG_IP_SET_HASH_IPPORT=m
-CONFIG_IP_SET_HASH_IPPORTIP=m
-CONFIG_IP_SET_HASH_IPPORTNET=m
-# CONFIG_IP_SET_HASH_IPMAC is not set
-CONFIG_IP_SET_HASH_MAC=m
-CONFIG_IP_SET_HASH_NETPORTNET=m
-CONFIG_IP_SET_HASH_NET=m
-CONFIG_IP_SET_HASH_NETNET=m
-CONFIG_IP_SET_HASH_NETPORT=m
-CONFIG_IP_SET_HASH_NETIFACE=m
-CONFIG_IP_SET_LIST_SET=m
-CONFIG_IP_VS=m
-CONFIG_IP_VS_IPV6=y
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_AH_ESP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-CONFIG_IP_VS_PROTO_SCTP=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_FO=m
-CONFIG_IP_VS_OVF=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-# CONFIG_IP_VS_MH is not set
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS SH scheduler
-#
-CONFIG_IP_VS_SH_TAB_BITS=8
-
-#
-# IPVS MH scheduler
-#
-CONFIG_IP_VS_MH_TAB_INDEX=12
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IP_VS_NFCT=y
-CONFIG_IP_VS_PE_SIP=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_DEFRAG_IPV4=m
-CONFIG_NF_SOCKET_IPV4=m
-CONFIG_NF_TPROXY_IPV4=m
-CONFIG_NF_TABLES_IPV4=y
-CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
-CONFIG_NFT_DUP_IPV4=m
-CONFIG_NFT_FIB_IPV4=m
-CONFIG_NF_TABLES_ARP=y
-CONFIG_NF_DUP_IPV4=m
-CONFIG_NF_LOG_ARP=m
-CONFIG_NF_LOG_IPV4=m
-CONFIG_NF_REJECT_IPV4=m
-CONFIG_NF_NAT_IPV4=m
-CONFIG_NF_NAT_MASQUERADE_IPV4=y
-CONFIG_NFT_CHAIN_NAT_IPV4=m
-CONFIG_NFT_MASQ_IPV4=m
-CONFIG_NFT_REDIR_IPV4=m
-CONFIG_NF_NAT_SNMP_BASIC=m
-CONFIG_NF_NAT_PROTO_GRE=m
-CONFIG_NF_NAT_PPTP=m
-CONFIG_NF_NAT_H323=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_AH=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_RPFILTER=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_SYNPROXY=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_MANGLE=m
-# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_SECURITY=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_NF_SOCKET_IPV6=m
-CONFIG_NF_TPROXY_IPV6=m
-CONFIG_NF_TABLES_IPV6=y
-CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-CONFIG_NFT_CHAIN_NAT_IPV6=m
-CONFIG_NFT_MASQ_IPV6=m
-CONFIG_NFT_REDIR_IPV6=m
-CONFIG_NFT_REJECT_IPV6=m
-CONFIG_NFT_DUP_IPV6=m
-CONFIG_NFT_FIB_IPV6=m
-CONFIG_NF_DUP_IPV6=m
-CONFIG_NF_REJECT_IPV6=m
-CONFIG_NF_LOG_IPV6=m
-CONFIG_NF_NAT_IPV6=m
-CONFIG_NF_NAT_MASQUERADE_IPV6=y
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_AH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_RPFILTER=m
-CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_MATCH_SRH is not set
-# CONFIG_IP6_NF_TARGET_HL is not set
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-CONFIG_IP6_NF_TARGET_SYNPROXY=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-CONFIG_IP6_NF_SECURITY=m
-CONFIG_IP6_NF_NAT=m
-CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_IP6_NF_TARGET_NPT=m
-CONFIG_NF_DEFRAG_IPV6=m
-CONFIG_NF_TABLES_BRIDGE=y
-CONFIG_NFT_BRIDGE_REJECT=m
-CONFIG_NF_LOG_BRIDGE=m
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_IP6=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_NFLOG=m
-# CONFIG_BPFILTER is not set
-# CONFIG_IP_DCCP is not set
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set
-CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y
-# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set
-CONFIG_SCTP_COOKIE_HMAC_MD5=y
-CONFIG_SCTP_COOKIE_HMAC_SHA1=y
-CONFIG_INET_SCTP_DIAG=m
-# CONFIG_RDS is not set
-CONFIG_TIPC=m
-# CONFIG_TIPC_MEDIA_IB is not set
-CONFIG_TIPC_MEDIA_UDP=y
-CONFIG_TIPC_DIAG=m
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-# CONFIG_ATM_MPOA is not set
-CONFIG_ATM_BR2684=m
-# CONFIG_ATM_BR2684_IPFILTER is not set
-CONFIG_L2TP=m
-CONFIG_L2TP_DEBUGFS=m
-CONFIG_L2TP_V3=y
-CONFIG_L2TP_IP=m
-CONFIG_L2TP_ETH=m
-CONFIG_STP=m
-CONFIG_GARP=m
-CONFIG_MRP=m
-CONFIG_BRIDGE=m
-CONFIG_BRIDGE_IGMP_SNOOPING=y
-CONFIG_BRIDGE_VLAN_FILTERING=y
-CONFIG_HAVE_NET_DSA=y
-# CONFIG_NET_DSA is not set
-CONFIG_VLAN_8021Q=m
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_VLAN_8021Q_MVRP=y
-# CONFIG_DECNET is not set
-CONFIG_LLC=m
-# CONFIG_LLC2 is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_PHONET is not set
-CONFIG_6LOWPAN=m
-# CONFIG_6LOWPAN_DEBUGFS is not set
-# CONFIG_6LOWPAN_NHC is not set
-CONFIG_IEEE802154=m
-# CONFIG_IEEE802154_NL802154_EXPERIMENTAL is not set
-CONFIG_IEEE802154_SOCKET=m
-# CONFIG_IEEE802154_6LOWPAN is not set
-CONFIG_MAC802154=m
-CONFIG_NET_SCHED=y
-
-#
-# Queueing/Scheduling
-#
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_MULTIQ=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFB=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-# CONFIG_NET_SCH_CBS is not set
-# CONFIG_NET_SCH_ETF is not set
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_DRR=m
-CONFIG_NET_SCH_MQPRIO=m
-# CONFIG_NET_SCH_SKBPRIO is not set
-CONFIG_NET_SCH_CHOKE=m
-CONFIG_NET_SCH_QFQ=m
-CONFIG_NET_SCH_CODEL=m
-CONFIG_NET_SCH_FQ_CODEL=m
-# CONFIG_NET_SCH_CAKE is not set
-CONFIG_NET_SCH_FQ=m
-CONFIG_NET_SCH_HHF=m
-CONFIG_NET_SCH_PIE=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_SCH_PLUG=m
-CONFIG_NET_SCH_DEFAULT=y
-# CONFIG_DEFAULT_FQ is not set
-# CONFIG_DEFAULT_CODEL is not set
-CONFIG_DEFAULT_FQ_CODEL=y
-# CONFIG_DEFAULT_SFQ is not set
-# CONFIG_DEFAULT_PFIFO_FAST is not set
-CONFIG_DEFAULT_NET_SCH="fq_codel"
-
-#
-# Classification
-#
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_BASIC=m
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_CLS_U32_PERF=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_CLS_FLOW=m
-CONFIG_NET_CLS_CGROUP=y
-CONFIG_NET_CLS_BPF=m
-CONFIG_NET_CLS_FLOWER=m
-CONFIG_NET_CLS_MATCHALL=m
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_STACK=32
-CONFIG_NET_EMATCH_CMP=m
-CONFIG_NET_EMATCH_NBYTE=m
-CONFIG_NET_EMATCH_U32=m
-CONFIG_NET_EMATCH_META=m
-CONFIG_NET_EMATCH_TEXT=m
-# CONFIG_NET_EMATCH_CANID is not set
-CONFIG_NET_EMATCH_IPSET=m
-# CONFIG_NET_EMATCH_IPT is not set
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=m
-CONFIG_NET_ACT_GACT=m
-CONFIG_GACT_PROB=y
-CONFIG_NET_ACT_MIRRED=m
-CONFIG_NET_ACT_SAMPLE=m
-# CONFIG_NET_ACT_IPT is not set
-CONFIG_NET_ACT_NAT=m
-CONFIG_NET_ACT_PEDIT=m
-CONFIG_NET_ACT_SIMP=m
-CONFIG_NET_ACT_SKBEDIT=m
-CONFIG_NET_ACT_CSUM=m
-CONFIG_NET_ACT_VLAN=m
-CONFIG_NET_ACT_BPF=m
-# CONFIG_NET_ACT_CONNMARK is not set
-CONFIG_NET_ACT_SKBMOD=m
-# CONFIG_NET_ACT_IFE is not set
-CONFIG_NET_ACT_TUNNEL_KEY=m
-CONFIG_NET_CLS_IND=y
-CONFIG_NET_SCH_FIFO=y
-CONFIG_DCB=y
-CONFIG_DNS_RESOLVER=m
-# CONFIG_BATMAN_ADV is not set
-CONFIG_OPENVSWITCH=m
-CONFIG_OPENVSWITCH_GRE=m
-CONFIG_OPENVSWITCH_VXLAN=m
-CONFIG_OPENVSWITCH_GENEVE=m
-CONFIG_VSOCKETS=m
-CONFIG_VSOCKETS_DIAG=m
-CONFIG_VIRTIO_VSOCKETS=m
-CONFIG_VIRTIO_VSOCKETS_COMMON=m
-CONFIG_NETLINK_DIAG=m
-CONFIG_MPLS=y
-CONFIG_NET_MPLS_GSO=m
-# CONFIG_MPLS_ROUTING is not set
-CONFIG_NET_NSH=m
-# CONFIG_HSR is not set
-CONFIG_NET_SWITCHDEV=y
-CONFIG_NET_L3_MASTER_DEV=y
-# CONFIG_QRTR is not set
-# CONFIG_NET_NCSI is not set
-CONFIG_RPS=y
-CONFIG_RFS_ACCEL=y
-CONFIG_XPS=y
-CONFIG_CGROUP_NET_PRIO=y
-CONFIG_CGROUP_NET_CLASSID=y
-CONFIG_NET_RX_BUSY_POLL=y
-CONFIG_BQL=y
-CONFIG_BPF_JIT=y
-# CONFIG_BPF_STREAM_PARSER is not set
-CONFIG_NET_FLOW_LIMIT=y
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-CONFIG_NET_DROP_MONITOR=m
-# CONFIG_HAMRADIO is not set
-CONFIG_CAN=m
-CONFIG_CAN_RAW=m
-CONFIG_CAN_BCM=m
-CONFIG_CAN_GW=m
-# CONFIG_CAN_J1939 is not set
-
-#
-# CAN Device Drivers
-#
-CONFIG_CAN_VCAN=m
-# CONFIG_CAN_VXCAN is not set
-CONFIG_CAN_SLCAN=m
-CONFIG_CAN_DEV=m
-CONFIG_CAN_CALC_BITTIMING=y
-# CONFIG_CAN_GRCAN is not set
-# CONFIG_CAN_XILINXCAN is not set
-CONFIG_CAN_C_CAN=m
-CONFIG_CAN_C_CAN_PLATFORM=m
-CONFIG_CAN_C_CAN_PCI=m
-CONFIG_CAN_CC770=m
-# CONFIG_CAN_CC770_ISA is not set
-CONFIG_CAN_CC770_PLATFORM=m
-# CONFIG_CAN_IFI_CANFD is not set
-# CONFIG_CAN_M_CAN is not set
-# CONFIG_CAN_PEAK_PCIEFD is not set
-CONFIG_CAN_SJA1000=m
-# CONFIG_CAN_SJA1000_ISA is not set
-CONFIG_CAN_SJA1000_PLATFORM=m
-CONFIG_CAN_EMS_PCI=m
-CONFIG_CAN_PEAK_PCI=m
-CONFIG_CAN_PEAK_PCIEC=y
-CONFIG_CAN_KVASER_PCI=m
-CONFIG_CAN_PLX_PCI=m
-CONFIG_CAN_SOFTING=m
-
-#
-# CAN SPI interfaces
-#
-# CONFIG_CAN_HI311X is not set
-# CONFIG_CAN_MCP251X is not set
-
-#
-# CAN USB interfaces
-#
-CONFIG_CAN_8DEV_USB=m
-CONFIG_CAN_EMS_USB=m
-CONFIG_CAN_ESD_USB2=m
-# CONFIG_CAN_GS_USB is not set
-CONFIG_CAN_KVASER_USB=m
-# CONFIG_CAN_MCBA_USB is not set
-CONFIG_CAN_PEAK_USB=m
-# CONFIG_CAN_UCAN is not set
-# CONFIG_CAN_DEBUG_DEVICES is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-# CONFIG_AF_KCM is not set
-CONFIG_STREAM_PARSER=m
-CONFIG_FIB_RULES=y
-CONFIG_WIRELESS=y
-CONFIG_WEXT_CORE=y
-CONFIG_WEXT_PROC=y
-CONFIG_CFG80211=m
-# CONFIG_NL80211_TESTMODE is not set
-# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
-# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
-CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
-CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
-CONFIG_CFG80211_DEFAULT_PS=y
-# CONFIG_CFG80211_DEBUGFS is not set
-CONFIG_CFG80211_CRDA_SUPPORT=y
-CONFIG_CFG80211_WEXT=y
-CONFIG_MAC80211=m
-CONFIG_MAC80211_HAS_RC=y
-CONFIG_MAC80211_RC_MINSTREL=y
-CONFIG_MAC80211_RC_MINSTREL_HT=y
-# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
-CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
-CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
-# CONFIG_MAC80211_MESH is not set
-CONFIG_MAC80211_LEDS=y
-CONFIG_MAC80211_DEBUGFS=y
-# CONFIG_MAC80211_MESSAGE_TRACING is not set
-# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
-# CONFIG_WIMAX is not set
-CONFIG_RFKILL=m
-CONFIG_RFKILL_LEDS=y
-CONFIG_RFKILL_INPUT=y
-CONFIG_RFKILL_GPIO=m
-# CONFIG_NET_9P is not set
-# CONFIG_CAIF is not set
-CONFIG_CEPH_LIB=m
-# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
-CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y
-# CONFIG_NFC is not set
-CONFIG_PSAMPLE=m
-# CONFIG_NET_IFE is not set
-CONFIG_LWTUNNEL=y
-CONFIG_LWTUNNEL_BPF=y
-CONFIG_DST_CACHE=y
-CONFIG_GRO_CELLS=y
-CONFIG_SOCK_VALIDATE_XMIT=y
-CONFIG_NET_DEVLINK=m
-CONFIG_MAY_USE_DEVLINK=m
-CONFIG_PAGE_POOL=y
-CONFIG_FAILOVER=m
-CONFIG_HAVE_EBPF_JIT=y
-
-#
-# Device Drivers
-#
-CONFIG_ARM_AMBA=y
-
-#
-# Generic Driver Options
-#
-# CONFIG_UEVENT_HELPER is not set
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-
-#
-# Firmware loader
-#
-CONFIG_FW_LOADER=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_FW_LOADER_USER_HELPER is not set
-CONFIG_WANT_DEV_COREDUMP=y
-# CONFIG_ALLOW_DEV_COREDUMP is not set
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
-# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
-CONFIG_GENERIC_CPU_AUTOPROBE=y
-CONFIG_REGMAP=y
-CONFIG_REGMAP_I2C=m
-CONFIG_REGMAP_SPI=m
-CONFIG_REGMAP_MMIO=y
-CONFIG_DMA_SHARED_BUFFER=y
-# CONFIG_DMA_FENCE_TRACE is not set
-CONFIG_DMA_CMA=y
-
-#
-# Default contiguous memory area size:
-#
-CONFIG_CMA_SIZE_MBYTES=64
-CONFIG_CMA_SIZE_SEL_MBYTES=y
-# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
-# CONFIG_CMA_SIZE_SEL_MIN is not set
-# CONFIG_CMA_SIZE_SEL_MAX is not set
-CONFIG_CMA_ALIGNMENT=8
-CONFIG_GENERIC_ARCH_TOPOLOGY=y
-
-#
-# Bus devices
-#
-# CONFIG_BRCMSTB_GISB_ARB is not set
-CONFIG_HISILICON_LPC=y
-CONFIG_QCOM_EBI2=y
-# CONFIG_SIMPLE_PM_BUS is not set
-CONFIG_VEXPRESS_CONFIG=y
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-# CONFIG_GNSS is not set
-CONFIG_MTD=m
-# CONFIG_MTD_TESTS is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=m
-# CONFIG_MTD_AFS_PARTS is not set
-CONFIG_MTD_OF_PARTS=m
-# CONFIG_MTD_AR7_PARTS is not set
-
-#
-# Partition parsers
-#
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_BLKDEVS=m
-CONFIG_MTD_BLOCK=m
-# CONFIG_MTD_BLOCK_RO is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_SM_FTL is not set
-# CONFIG_MTD_OOPS is not set
-# CONFIG_MTD_SWAP is not set
-# CONFIG_MTD_PARTITIONED_MASTER is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=m
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=m
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_MAP_BANK_WIDTH_8=y
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
-CONFIG_MTD_CFI_INTELEXT=m
-CONFIG_MTD_CFI_AMDSTD=m
-CONFIG_MTD_CFI_STAA=m
-CONFIG_MTD_CFI_UTIL=m
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=m
-# CONFIG_MTD_PHYSMAP_COMPAT is not set
-CONFIG_MTD_PHYSMAP_OF=m
-# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set
-# CONFIG_MTD_PHYSMAP_OF_GEMINI is not set
-# CONFIG_MTD_INTEL_VR_NOR is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
-# CONFIG_MTD_MCHP23K256 is not set
-# CONFIG_MTD_SST25L is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLOCK2MTD=m
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOCG3 is not set
-# CONFIG_MTD_ONENAND is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_SPI_NAND is not set
-
-#
-# LPDDR & LPDDR2 PCM memory drivers
-#
-# CONFIG_MTD_LPDDR is not set
-CONFIG_MTD_SPI_NOR=m
-CONFIG_MTD_MT81xx_NOR=m
-CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
-# CONFIG_SPI_CADENCE_QUADSPI is not set
-CONFIG_SPI_HISI_SFC=m
-CONFIG_MTD_UBI=m
-CONFIG_MTD_UBI_WL_THRESHOLD=4096
-CONFIG_MTD_UBI_BEB_LIMIT=20
-# CONFIG_MTD_UBI_FASTMAP is not set
-CONFIG_MTD_UBI_GLUEBI=m
-# CONFIG_MTD_UBI_BLOCK is not set
-CONFIG_DTC=y
-CONFIG_OF=y
-# CONFIG_OF_UNITTEST is not set
-CONFIG_OF_FLATTREE=y
-CONFIG_OF_EARLY_FLATTREE=y
-CONFIG_OF_KOBJ=y
-CONFIG_OF_DYNAMIC=y
-CONFIG_OF_ADDRESS=y
-CONFIG_OF_IRQ=y
-CONFIG_OF_NET=y
-CONFIG_OF_MDIO=y
-CONFIG_OF_RESERVED_MEM=y
-CONFIG_OF_RESOLVE=y
-CONFIG_OF_OVERLAY=y
-CONFIG_OF_NUMA=y
-# CONFIG_PARPORT is not set
-CONFIG_PNP=y
-CONFIG_PNP_DEBUG_MESSAGES=y
-
-#
-# Protocols
-#
-CONFIG_PNPACPI=y
-CONFIG_BLK_DEV=y
-CONFIG_BLK_DEV_NULL_BLK=m
-CONFIG_CDROM=m
-# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
-CONFIG_ZRAM=m
-# CONFIG_ZRAM_WRITEBACK is not set
-# CONFIG_ZRAM_MEMORY_TRACKING is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_DRBD is not set
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_SKD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=m
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-# CONFIG_ATA_OVER_ETH is not set
-CONFIG_VIRTIO_BLK=m
-CONFIG_VIRTIO_BLK_SCSI=y
-CONFIG_BLK_DEV_RBD=m
-# CONFIG_BLK_DEV_RSXX is not set
-
-#
-# NVME Support
-#
-CONFIG_NVME_CORE=m
-CONFIG_BLK_DEV_NVME=m
-# CONFIG_NVME_MULTIPATH is not set
-CONFIG_NVME_FABRICS=m
-CONFIG_NVME_RDMA=m
-CONFIG_NVME_FC=m
-CONFIG_NVME_TARGET=m
-CONFIG_NVME_TARGET_LOOP=m
-CONFIG_NVME_TARGET_RDMA=m
-CONFIG_NVME_TARGET_FC=m
-CONFIG_NVME_TARGET_FCLOOP=m
-
-#
-# Misc devices
-#
-CONFIG_SENSORS_LIS3LV02D=m
-# CONFIG_AD525X_DPOT is not set
-# CONFIG_DUMMY_IRQ is not set
-# CONFIG_PHANTOM is not set
-# CONFIG_SGI_IOC4 is not set
-CONFIG_TIFM_CORE=m
-CONFIG_TIFM_7XX1=m
-# CONFIG_ICS932S401 is not set
-CONFIG_ENCLOSURE_SERVICES=m
-# CONFIG_HP_ILO is not set
-CONFIG_APDS9802ALS=m
-CONFIG_ISL29003=m
-CONFIG_ISL29020=m
-CONFIG_SENSORS_TSL2550=m
-CONFIG_SENSORS_BH1770=m
-CONFIG_SENSORS_APDS990X=m
-# CONFIG_HMC6352 is not set
-# CONFIG_DS1682 is not set
-# CONFIG_USB_SWITCH_FSA9480 is not set
-# CONFIG_LATTICE_ECP3_CONFIG is not set
-# CONFIG_SRAM is not set
-CONFIG_VEXPRESS_SYSCFG=y
-# CONFIG_PCI_ENDPOINT_TEST is not set
-# CONFIG_C2PORT is not set
-
-#
-# EEPROM support
-#
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_AT25 is not set
-CONFIG_EEPROM_LEGACY=m
-CONFIG_EEPROM_MAX6875=m
-CONFIG_EEPROM_93CX6=m
-# CONFIG_EEPROM_93XX46 is not set
-# CONFIG_EEPROM_IDT_89HPESX is not set
-CONFIG_CB710_CORE=m
-# CONFIG_CB710_DEBUG is not set
-CONFIG_CB710_DEBUG_ASSUMPTIONS=y
-
-#
-# Texas Instruments shared transport line discipline
-#
-# CONFIG_TI_ST is not set
-CONFIG_SENSORS_LIS3_I2C=m
-
-#
-# Altera FPGA firmware download module (requires I2C)
-#
-CONFIG_ALTERA_STAPL=m
-
-#
-# Intel MIC & related support
-#
-
-#
-# Intel MIC Bus Driver
-#
-
-#
-# SCIF Bus Driver
-#
-
-#
-# VOP Bus Driver
-#
-
-#
-# Intel MIC Host Driver
-#
-
-#
-# Intel MIC Card Driver
-#
-
-#
-# SCIF Driver
-#
-
-#
-# Intel MIC Coprocessor State Management (COSM) Drivers
-#
-
-#
-# VOP Driver
-#
-# CONFIG_GENWQE is not set
-# CONFIG_ECHO is not set
-# CONFIG_MISC_RTSX_PCI is not set
-# CONFIG_MISC_RTSX_USB is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI_MOD=y
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-CONFIG_SCSI_NETLINK=y
-CONFIG_SCSI_MQ_DEFAULT=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=m
-CONFIG_CHR_DEV_ST=m
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=m
-CONFIG_CHR_DEV_SCH=m
-CONFIG_SCSI_ENCLOSURE=m
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-
-#
-# SCSI Transports
-#
-CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-CONFIG_SCSI_SAS_ATA=y
-CONFIG_SCSI_SAS_HOST_SMP=y
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_LOWLEVEL=y
-CONFIG_ISCSI_TCP=m
-CONFIG_ISCSI_BOOT_SYSFS=m
-# CONFIG_SCSI_CXGB3_ISCSI is not set
-CONFIG_SCSI_CXGB4_ISCSI=m
-CONFIG_SCSI_BNX2_ISCSI=m
-CONFIG_SCSI_BNX2X_FCOE=m
-CONFIG_BE2ISCSI=m
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-CONFIG_SCSI_HPSA=m
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_3W_SAS is not set
-# CONFIG_SCSI_ACARD is not set
-CONFIG_SCSI_AACRAID=m
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-CONFIG_SCSI_HISI_SAS=m
-CONFIG_SCSI_HISI_SAS_PCI=m
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_MVUMI is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_SCSI_ESAS2R is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-CONFIG_MEGARAID_SAS=m
-CONFIG_SCSI_MPT3SAS=m
-CONFIG_SCSI_MPT2SAS_MAX_SGE=128
-CONFIG_SCSI_MPT3SAS_MAX_SGE=128
-CONFIG_SCSI_MPT2SAS=m
-CONFIG_SCSI_SMARTPQI=m
-# CONFIG_SCSI_UFSHCD is not set
-# CONFIG_SCSI_HPTIOP is not set
-CONFIG_LIBFC=m
-CONFIG_LIBFCOE=m
-# CONFIG_FCOE is not set
-# CONFIG_SCSI_SNIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-CONFIG_SCSI_IPR=m
-CONFIG_SCSI_IPR_TRACE=y
-CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA_FC=m
-# CONFIG_TCM_QLA2XXX is not set
-CONFIG_SCSI_QLA_ISCSI=m
-CONFIG_QEDI=m
-CONFIG_QEDF=m
-# CONFIG_SCSI_HUAWEI_FC is not set
-CONFIG_SCSI_LPFC=m
-# CONFIG_SCSI_LPFC_DEBUG_FS is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_WD719X is not set
-CONFIG_SCSI_DEBUG=m
-# CONFIG_SCSI_PMCRAID is not set
-# CONFIG_SCSI_PM8001 is not set
-# CONFIG_SCSI_BFA_FC is not set
-CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_CHELSIO_FCOE=m
-# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
-CONFIG_SCSI_DH=y
-CONFIG_SCSI_DH_RDAC=y
-CONFIG_SCSI_DH_HP_SW=y
-CONFIG_SCSI_DH_EMC=y
-CONFIG_SCSI_DH_ALUA=y
-# CONFIG_SCSI_OSD_INITIATOR is not set
-CONFIG_HAVE_PATA_PLATFORM=y
-CONFIG_ATA=m
-CONFIG_ATA_VERBOSE_ERROR=y
-CONFIG_ATA_ACPI=y
-# CONFIG_SATA_ZPODD is not set
-CONFIG_SATA_PMP=y
-
-#
-# Controllers with non-SFF native interface
-#
-CONFIG_SATA_AHCI=m
-CONFIG_SATA_MOBILE_LPM_POLICY=0
-CONFIG_SATA_AHCI_PLATFORM=m
-# CONFIG_AHCI_CEVA is not set
-CONFIG_AHCI_XGENE=m
-# CONFIG_AHCI_QORIQ is not set
-CONFIG_SATA_AHCI_SEATTLE=m
-# CONFIG_SATA_INIC162X is not set
-# CONFIG_SATA_ACARD_AHCI is not set
-# CONFIG_SATA_SIL24 is not set
-CONFIG_ATA_SFF=y
-
-#
-# SFF controllers with custom DMA interface
-#
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_SX4 is not set
-CONFIG_ATA_BMDMA=y
-
-#
-# SATA SFF controllers with BMDMA
-#
-CONFIG_ATA_PIIX=m
-# CONFIG_SATA_DWC is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_SVW is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-
-#
-# PATA SFF controllers with BMDMA
-#
-# CONFIG_PATA_ALI is not set
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_ATP867X is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
-# CONFIG_PATA_NS87415 is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RDC is not set
-# CONFIG_PATA_SCH is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_TOSHIBA is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-
-#
-# PIO-only SFF controllers
-#
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_PLATFORM is not set
-# CONFIG_PATA_RZ1000 is not set
-
-#
-# Generic fallback / legacy drivers
-#
-# CONFIG_PATA_ACPI is not set
-CONFIG_ATA_GENERIC=m
-# CONFIG_PATA_LEGACY is not set
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_AUTODETECT=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID10=m
-CONFIG_MD_RAID456=m
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_MD_FAULTY=m
-# CONFIG_BCACHE is not set
-CONFIG_BLK_DEV_DM_BUILTIN=y
-CONFIG_BLK_DEV_DM=m
-# CONFIG_DM_MQ_DEFAULT is not set
-CONFIG_DM_DEBUG=y
-CONFIG_DM_BUFIO=m
-# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
-CONFIG_DM_BIO_PRISON=m
-CONFIG_DM_PERSISTENT_DATA=m
-# CONFIG_DM_UNSTRIPED is not set
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
-CONFIG_DM_CACHE_SMQ=m
-# CONFIG_DM_WRITECACHE is not set
-CONFIG_DM_ERA=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_LOG_USERSPACE=m
-CONFIG_DM_RAID=m
-CONFIG_DM_ZERO=m
-CONFIG_DM_MULTIPATH=m
-CONFIG_DM_MULTIPATH_QL=m
-CONFIG_DM_MULTIPATH_ST=m
-CONFIG_DM_DELAY=m
-CONFIG_DM_UEVENT=y
-CONFIG_DM_FLAKEY=m
-CONFIG_DM_VERITY=m
-# CONFIG_DM_VERITY_FEC is not set
-CONFIG_DM_SWITCH=m
-CONFIG_DM_LOG_WRITES=m
-CONFIG_DM_INTEGRITY=m
-# CONFIG_DM_ZONED is not set
-CONFIG_TARGET_CORE=m
-CONFIG_TCM_IBLOCK=m
-CONFIG_TCM_FILEIO=m
-CONFIG_TCM_PSCSI=m
-CONFIG_TCM_USER2=m
-CONFIG_LOOPBACK_TARGET=m
-CONFIG_TCM_FC=m
-CONFIG_ISCSI_TARGET=m
-CONFIG_ISCSI_TARGET_CXGB4=m
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_FIREWIRE_NOSY is not set
-CONFIG_NETDEVICES=y
-CONFIG_MII=m
-CONFIG_NET_CORE=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-# CONFIG_EQUALIZER is not set
-CONFIG_NET_FC=y
-CONFIG_IFB=m
-CONFIG_NET_TEAM=m
-CONFIG_NET_TEAM_MODE_BROADCAST=m
-CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
-CONFIG_NET_TEAM_MODE_RANDOM=m
-CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
-CONFIG_NET_TEAM_MODE_LOADBALANCE=m
-CONFIG_MACVLAN=m
-CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
-CONFIG_IPVTAP=m
-CONFIG_VXLAN=m
-CONFIG_GENEVE=m
-# CONFIG_GTP is not set
-CONFIG_MACSEC=m
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_NETPOLL=y
-CONFIG_NET_POLL_CONTROLLER=y
-CONFIG_TUN=m
-CONFIG_TAP=m
-# CONFIG_TUN_VNET_CROSS_LE is not set
-CONFIG_VETH=m
-CONFIG_VIRTIO_NET=m
-CONFIG_NLMON=m
-CONFIG_NET_VRF=m
-CONFIG_VSOCKMON=m
-# CONFIG_ARCNET is not set
-# CONFIG_ATM_DRIVERS is not set
-
-#
-# CAIF transport drivers
-#
-
-#
-# Distributed Switch Architecture drivers
-#
-CONFIG_ETHERNET=y
-CONFIG_MDIO=m
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_ADAPTEC is not set
-# CONFIG_NET_VENDOR_AGERE is not set
-CONFIG_NET_VENDOR_ALACRITECH=y
-# CONFIG_SLICOSS is not set
-# CONFIG_NET_VENDOR_ALTEON is not set
-# CONFIG_ALTERA_TSE is not set
-CONFIG_NET_VENDOR_AMAZON=y
-CONFIG_NET_VENDOR_AMD=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_PCNET32 is not set
-CONFIG_AMD_XGBE=m
-# CONFIG_AMD_XGBE_DCB is not set
-CONFIG_NET_XGENE=y
-CONFIG_NET_XGENE_V2=m
-CONFIG_NET_VENDOR_AQUANTIA=y
-CONFIG_NET_VENDOR_ARC=y
-CONFIG_NET_VENDOR_ATHEROS=y
-# CONFIG_ATL2 is not set
-CONFIG_ATL1=m
-CONFIG_ATL1E=m
-CONFIG_ATL1C=m
-CONFIG_ALX=m
-# CONFIG_NET_VENDOR_AURORA is not set
-CONFIG_NET_VENDOR_BROADCOM=y
-# CONFIG_B44 is not set
-# CONFIG_BCMGENET is not set
-CONFIG_BNX2=m
-CONFIG_CNIC=m
-CONFIG_TIGON3=m
-CONFIG_TIGON3_HWMON=y
-CONFIG_BNX2X=m
-CONFIG_BNX2X_SRIOV=y
-# CONFIG_SYSTEMPORT is not set
-CONFIG_BNXT=m
-CONFIG_BNXT_SRIOV=y
-CONFIG_BNXT_FLOWER_OFFLOAD=y
-CONFIG_BNXT_DCB=y
-# CONFIG_BNXT_HWMON is not set
-# CONFIG_NET_VENDOR_BROCADE is not set
-# CONFIG_NET_VENDOR_CADENCE is not set
-CONFIG_NET_VENDOR_CAVIUM=y
-CONFIG_THUNDER_NIC_PF=m
-CONFIG_THUNDER_NIC_VF=m
-CONFIG_THUNDER_NIC_BGX=m
-CONFIG_THUNDER_NIC_RGX=m
-CONFIG_CAVIUM_PTP=y
-CONFIG_LIQUIDIO=m
-CONFIG_LIQUIDIO_VF=m
-CONFIG_NET_VENDOR_CHELSIO=y
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_CHELSIO_T3 is not set
-CONFIG_CHELSIO_T4=m
-# CONFIG_CHELSIO_T4_DCB is not set
-CONFIG_CHELSIO_T4VF=m
-CONFIG_CHELSIO_LIB=m
-# CONFIG_NET_VENDOR_CISCO is not set
-# CONFIG_NET_VENDOR_CORTINA is not set
-CONFIG_DNET=m
-# CONFIG_NET_VENDOR_DEC is not set
-# CONFIG_NET_VENDOR_DLINK is not set
-# CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_EZCHIP is not set
-CONFIG_NET_VENDOR_HISILICON=y
-# CONFIG_HIX5HD2_GMAC is not set
-# CONFIG_HISI_FEMAC is not set
-# CONFIG_HIP04_ETH is not set
-CONFIG_HNS_MDIO=m
-CONFIG_HNS=m
-CONFIG_HNS_DSAF=m
-CONFIG_HNS_ENET=m
-CONFIG_HNS3=m
-CONFIG_HNS3_HCLGE=m
-CONFIG_HNS3_DCB=y
-CONFIG_HNS3_HCLGEVF=m
-CONFIG_HNS3_ENET=m
-# CONFIG_NET_VENDOR_HP is not set
-CONFIG_NET_VENDOR_HUAWEI=y
-CONFIG_HINIC=m
-# CONFIG_BMA is not set
-# CONFIG_NET_VENDOR_I825XX is not set
-CONFIG_NET_VENDOR_INTEL=y
-# CONFIG_E100 is not set
-CONFIG_E1000=m
-CONFIG_E1000E=m
-CONFIG_IGB=m
-CONFIG_IGB_HWMON=y
-CONFIG_IGBVF=m
-# CONFIG_IXGB is not set
-CONFIG_IXGBE=m
-CONFIG_IXGBE_HWMON=y
-CONFIG_IXGBE_DCB=y
-CONFIG_IXGBEVF=m
-CONFIG_I40E=m
-# CONFIG_I40E_DCB is not set
-CONFIG_I40EVF=m
-CONFIG_ICE=m
-CONFIG_FM10K=m
-# CONFIG_JME is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-CONFIG_NET_VENDOR_MELLANOX=y
-CONFIG_MLX4_EN=m
-CONFIG_MLX4_EN_DCB=y
-CONFIG_MLX4_CORE=m
-CONFIG_MLX4_DEBUG=y
-# CONFIG_MLX4_CORE_GEN2 is not set
-CONFIG_MLX5_CORE=m
-# CONFIG_MLX5_FPGA is not set
-CONFIG_MLX5_CORE_EN=y
-CONFIG_MLX5_EN_ARFS=y
-CONFIG_MLX5_EN_RXNFC=y
-CONFIG_MLX5_MPFS=y
-# CONFIG_MLX5_ESWITCH is not set
-CONFIG_MLX5_CORE_EN_DCB=y
-CONFIG_MLX5_CORE_IPOIB=y
-CONFIG_MLXSW_CORE=m
-CONFIG_MLXSW_CORE_HWMON=y
-CONFIG_MLXSW_CORE_THERMAL=y
-CONFIG_MLXSW_PCI=m
-CONFIG_MLXSW_I2C=m
-# CONFIG_MLXSW_SWITCHIB is not set
-# CONFIG_MLXSW_SWITCHX2 is not set
-# CONFIG_MLXSW_SPECTRUM is not set
-CONFIG_MLXSW_MINIMAL=m
-CONFIG_MLXFW=m
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_MICROCHIP is not set
-CONFIG_NET_VENDOR_MICROSEMI=y
-# CONFIG_MSCC_OCELOT_SWITCH is not set
-CONFIG_NET_VENDOR_MYRI=y
-# CONFIG_MYRI10GE is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_NETERION is not set
-CONFIG_NET_VENDOR_NETRONOME=y
-CONFIG_NFP=m
-CONFIG_NFP_APP_FLOWER=y
-CONFIG_NFP_APP_ABM_NIC=y
-# CONFIG_NFP_DEBUG is not set
-# CONFIG_NET_VENDOR_NI is not set
-# CONFIG_NET_VENDOR_NVIDIA is not set
-CONFIG_NET_VENDOR_OKI=y
-CONFIG_ETHOC=m
-# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
-CONFIG_NET_VENDOR_QLOGIC=y
-CONFIG_QLA3XXX=m
-# CONFIG_QLCNIC is not set
-# CONFIG_QLGE is not set
-CONFIG_NETXEN_NIC=m
-CONFIG_QED=m
-CONFIG_QED_LL2=y
-CONFIG_QED_SRIOV=y
-CONFIG_QEDE=m
-CONFIG_QED_RDMA=y
-CONFIG_QED_ISCSI=y
-CONFIG_QED_FCOE=y
-CONFIG_QED_OOO=y
-CONFIG_NET_VENDOR_QUALCOMM=y
-# CONFIG_QCA7000_SPI is not set
-CONFIG_QCOM_EMAC=m
-# CONFIG_RMNET is not set
-# CONFIG_NET_VENDOR_RDC is not set
-CONFIG_NET_VENDOR_REALTEK=y
-CONFIG_8139CP=m
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-CONFIG_8139TOO_8129=y
-# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_R8169=m
-# CONFIG_NET_VENDOR_RENESAS is not set
-CONFIG_NET_VENDOR_ROCKER=y
-CONFIG_ROCKER=m
-# CONFIG_NET_VENDOR_SAMSUNG is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-CONFIG_NET_VENDOR_SOLARFLARE=y
-CONFIG_SFC=m
-CONFIG_SFC_MTD=y
-CONFIG_SFC_MCDI_MON=y
-CONFIG_SFC_SRIOV=y
-CONFIG_SFC_MCDI_LOGGING=y
-# CONFIG_SFC_FALCON is not set
-# CONFIG_NET_VENDOR_SILAN is not set
-# CONFIG_NET_VENDOR_SIS is not set
-CONFIG_NET_VENDOR_SMSC=y
-CONFIG_SMC91X=m
-CONFIG_EPIC100=m
-CONFIG_SMSC911X=m
-CONFIG_SMSC9420=m
-# CONFIG_NET_VENDOR_SOCIONEXT is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_SUN is not set
-# CONFIG_NET_VENDOR_SYNOPSYS is not set
-# CONFIG_NET_VENDOR_TEHUTI is not set
-# CONFIG_NET_VENDOR_TI is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_NET_SB1000 is not set
-CONFIG_MDIO_DEVICE=y
-CONFIG_MDIO_BUS=y
-CONFIG_MDIO_BCM_UNIMAC=m
-CONFIG_MDIO_BITBANG=m
-# CONFIG_MDIO_BUS_MUX_GPIO is not set
-# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
-CONFIG_MDIO_CAVIUM=m
-CONFIG_MDIO_GPIO=m
-# CONFIG_MDIO_HISI_FEMAC is not set
-# CONFIG_MDIO_MSCC_MIIM is not set
-CONFIG_MDIO_OCTEON=m
-CONFIG_MDIO_THUNDER=m
-CONFIG_MDIO_XGENE=y
-CONFIG_PHYLIB=y
-CONFIG_SWPHY=y
-# CONFIG_LED_TRIGGER_PHY is not set
-
-#
-# MII PHY device drivers
-#
-CONFIG_AMD_PHY=m
-CONFIG_AQUANTIA_PHY=m
-# CONFIG_ASIX_PHY is not set
-CONFIG_AT803X_PHY=m
-# CONFIG_BCM7XXX_PHY is not set
-CONFIG_BCM87XX_PHY=m
-CONFIG_BCM_NET_PHYLIB=m
-CONFIG_BROADCOM_PHY=m
-CONFIG_CICADA_PHY=m
-# CONFIG_CORTINA_PHY is not set
-CONFIG_DAVICOM_PHY=m
-# CONFIG_DP83822_PHY is not set
-# CONFIG_DP83TC811_PHY is not set
-CONFIG_DP83848_PHY=m
-CONFIG_DP83867_PHY=m
-CONFIG_FIXED_PHY=y
-CONFIG_ICPLUS_PHY=m
-# CONFIG_INTEL_XWAY_PHY is not set
-CONFIG_LSI_ET1011C_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_MARVELL_PHY=m
-# CONFIG_MARVELL_10G_PHY is not set
-CONFIG_MICREL_PHY=m
-CONFIG_MICROCHIP_PHY=m
-# CONFIG_MICROCHIP_T1_PHY is not set
-# CONFIG_MICROSEMI_PHY is not set
-CONFIG_NATIONAL_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_REALTEK_PHY=m
-# CONFIG_RENESAS_PHY is not set
-# CONFIG_ROCKCHIP_PHY is not set
-CONFIG_SMSC_PHY=m
-CONFIG_STE10XP=m
-CONFIG_TERANETICS_PHY=m
-CONFIG_VITESSE_PHY=m
-# CONFIG_XILINX_GMII2RGMII is not set
-# CONFIG_MICREL_KS8995MA is not set
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_MPPE=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOATM=m
-CONFIG_PPPOE=m
-CONFIG_PPTP=m
-CONFIG_PPPOL2TP=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_SLIP=m
-CONFIG_SLHC=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
-CONFIG_USB_NET_DRIVERS=y
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_RTL8152=m
-CONFIG_USB_LAN78XX=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_AX8817X=m
-CONFIG_USB_NET_AX88179_178A=m
-CONFIG_USB_NET_CDCETHER=m
-CONFIG_USB_NET_CDC_EEM=m
-CONFIG_USB_NET_CDC_NCM=m
-CONFIG_USB_NET_HUAWEI_CDC_NCM=m
-CONFIG_USB_NET_CDC_MBIM=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_SR9700=m
-# CONFIG_USB_NET_SR9800 is not set
-CONFIG_USB_NET_SMSC75XX=m
-CONFIG_USB_NET_SMSC95XX=m
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_NET1080=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
-CONFIG_USB_NET_RNDIS_HOST=m
-CONFIG_USB_NET_CDC_SUBSET_ENABLE=m
-CONFIG_USB_NET_CDC_SUBSET=m
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=m
-CONFIG_USB_NET_CX82310_ETH=m
-CONFIG_USB_NET_KALMIA=m
-CONFIG_USB_NET_QMI_WWAN=m
-CONFIG_USB_HSO=m
-CONFIG_USB_NET_INT51X1=m
-CONFIG_USB_IPHETH=m
-CONFIG_USB_SIERRA_NET=m
-CONFIG_USB_VL600=m
-CONFIG_USB_NET_CH9200=m
-CONFIG_WLAN=y
-# CONFIG_WIRELESS_WDS is not set
-# CONFIG_WLAN_VENDOR_ADMTEK is not set
-CONFIG_ATH_COMMON=m
-CONFIG_WLAN_VENDOR_ATH=y
-# CONFIG_ATH_DEBUG is not set
-# CONFIG_ATH5K is not set
-# CONFIG_ATH5K_PCI is not set
-# CONFIG_ATH9K is not set
-# CONFIG_ATH9K_HTC is not set
-# CONFIG_CARL9170 is not set
-# CONFIG_ATH6KL is not set
-# CONFIG_AR5523 is not set
-# CONFIG_WIL6210 is not set
-CONFIG_ATH10K=m
-CONFIG_ATH10K_CE=y
-CONFIG_ATH10K_PCI=m
-# CONFIG_ATH10K_AHB is not set
-# CONFIG_ATH10K_SDIO is not set
-# CONFIG_ATH10K_USB is not set
-# CONFIG_ATH10K_SNOC is not set
-# CONFIG_ATH10K_DEBUG is not set
-# CONFIG_ATH10K_DEBUGFS is not set
-# CONFIG_ATH10K_TRACING is not set
-# CONFIG_WCN36XX is not set
-# CONFIG_WLAN_VENDOR_ATMEL is not set
-# CONFIG_WLAN_VENDOR_BROADCOM is not set
-# CONFIG_WLAN_VENDOR_CISCO is not set
-# CONFIG_WLAN_VENDOR_INTEL is not set
-# CONFIG_WLAN_VENDOR_INTERSIL is not set
-# CONFIG_WLAN_VENDOR_MARVELL is not set
-# CONFIG_WLAN_VENDOR_MEDIATEK is not set
-CONFIG_WLAN_VENDOR_RALINK=y
-CONFIG_RT2X00=m
-# CONFIG_RT2400PCI is not set
-# CONFIG_RT2500PCI is not set
-# CONFIG_RT61PCI is not set
-# CONFIG_RT2800PCI is not set
-# CONFIG_RT2500USB is not set
-# CONFIG_RT73USB is not set
-CONFIG_RT2800USB=m
-CONFIG_RT2800USB_RT33XX=y
-CONFIG_RT2800USB_RT35XX=y
-# CONFIG_RT2800USB_RT3573 is not set
-CONFIG_RT2800USB_RT53XX=y
-# CONFIG_RT2800USB_RT55XX is not set
-# CONFIG_RT2800USB_UNKNOWN is not set
-CONFIG_RT2800_LIB=m
-CONFIG_RT2X00_LIB_USB=m
-CONFIG_RT2X00_LIB=m
-CONFIG_RT2X00_LIB_FIRMWARE=y
-CONFIG_RT2X00_LIB_CRYPTO=y
-CONFIG_RT2X00_LIB_LEDS=y
-# CONFIG_RT2X00_LIB_DEBUGFS is not set
-# CONFIG_RT2X00_DEBUG is not set
-# CONFIG_WLAN_VENDOR_REALTEK is not set
-# CONFIG_WLAN_VENDOR_RSI is not set
-# CONFIG_WLAN_VENDOR_ST is not set
-# CONFIG_WLAN_VENDOR_TI is not set
-# CONFIG_WLAN_VENDOR_ZYDAS is not set
-# CONFIG_WLAN_VENDOR_QUANTENNA is not set
-# CONFIG_MAC80211_HWSIM is not set
-# CONFIG_USB_NET_RNDIS_WLAN is not set
-
-#
-# Enable WiMAX (Networking options) to see the WiMAX drivers
-#
-CONFIG_WAN=y
-CONFIG_HDLC=m
-CONFIG_HDLC_RAW=m
-# CONFIG_HDLC_RAW_ETH is not set
-CONFIG_HDLC_CISCO=m
-CONFIG_HDLC_FR=m
-CONFIG_HDLC_PPP=m
-
-#
-# X.25/LAPB support is disabled
-#
-# CONFIG_PCI200SYN is not set
-# CONFIG_WANXL is not set
-# CONFIG_PC300TOO is not set
-# CONFIG_FARSYNC is not set
-# CONFIG_DSCC4 is not set
-CONFIG_DLCI=m
-CONFIG_DLCI_MAX=8
-# CONFIG_IEEE802154_DRIVERS is not set
-# CONFIG_VMXNET3 is not set
-# CONFIG_FUJITSU_ES is not set
-# CONFIG_NETDEVSIM is not set
-CONFIG_NET_FAILOVER=m
-# CONFIG_ISDN is not set
-# CONFIG_NVM is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_LEDS=y
-CONFIG_INPUT_FF_MEMLESS=m
-CONFIG_INPUT_POLLDEV=m
-CONFIG_INPUT_SPARSEKMAP=m
-# CONFIG_INPUT_MATRIXKMAP is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ADP5588 is not set
-# CONFIG_KEYBOARD_ADP5589 is not set
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_QT1070 is not set
-# CONFIG_KEYBOARD_QT2160 is not set
-# CONFIG_KEYBOARD_DLINK_DIR685 is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_GPIO is not set
-# CONFIG_KEYBOARD_GPIO_POLLED is not set
-# CONFIG_KEYBOARD_TCA6416 is not set
-# CONFIG_KEYBOARD_TCA8418 is not set
-# CONFIG_KEYBOARD_MATRIX is not set
-# CONFIG_KEYBOARD_LM8323 is not set
-# CONFIG_KEYBOARD_LM8333 is not set
-# CONFIG_KEYBOARD_MAX7359 is not set
-# CONFIG_KEYBOARD_MCS is not set
-# CONFIG_KEYBOARD_MPR121 is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_OPENCORES is not set
-# CONFIG_KEYBOARD_SAMSUNG is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_OMAP4 is not set
-# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_CAP11XX is not set
-# CONFIG_KEYBOARD_BCM is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-CONFIG_MOUSE_PS2_ALPS=y
-CONFIG_MOUSE_PS2_BYD=y
-CONFIG_MOUSE_PS2_LOGIPS2PP=y
-CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_CYPRESS=y
-CONFIG_MOUSE_PS2_TRACKPOINT=y
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_MOUSE_PS2_SENTELIC=y
-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
-CONFIG_MOUSE_PS2_FOCALTECH=y
-CONFIG_MOUSE_SERIAL=m
-CONFIG_MOUSE_APPLETOUCH=m
-CONFIG_MOUSE_BCM5974=m
-CONFIG_MOUSE_CYAPA=m
-# CONFIG_MOUSE_ELAN_I2C is not set
-CONFIG_MOUSE_VSXXXAA=m
-# CONFIG_MOUSE_GPIO is not set
-CONFIG_MOUSE_SYNAPTICS_I2C=m
-CONFIG_MOUSE_SYNAPTICS_USB=m
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-CONFIG_RMI4_CORE=m
-CONFIG_RMI4_I2C=m
-CONFIG_RMI4_SPI=m
-CONFIG_RMI4_SMB=m
-CONFIG_RMI4_F03=y
-CONFIG_RMI4_F03_SERIO=m
-CONFIG_RMI4_2D_SENSOR=y
-CONFIG_RMI4_F11=y
-CONFIG_RMI4_F12=y
-CONFIG_RMI4_F30=y
-# CONFIG_RMI4_F34 is not set
-# CONFIG_RMI4_F55 is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-CONFIG_SERIO_AMBAKMI=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-CONFIG_SERIO_ALTERA_PS2=m
-# CONFIG_SERIO_PS2MULT is not set
-CONFIG_SERIO_ARC_PS2=m
-# CONFIG_SERIO_APBPS2 is not set
-# CONFIG_SERIO_GPIO_PS2 is not set
-# CONFIG_USERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_TTY=y
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_VT_CONSOLE_SLEEP=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_ROCKETPORT is not set
-CONFIG_CYCLADES=m
-# CONFIG_CYZ_INTR is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-CONFIG_SYNCLINKMP=m
-CONFIG_SYNCLINK_GT=m
-# CONFIG_NOZOMI is not set
-# CONFIG_ISI is not set
-CONFIG_N_HDLC=m
-CONFIG_N_GSM=m
-# CONFIG_TRACE_SINK is not set
-CONFIG_DEVMEM=y
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_EARLYCON=y
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
-CONFIG_SERIAL_8250_PNP=y
-# CONFIG_SERIAL_8250_FINTEK is not set
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_DMA=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_EXAR=y
-CONFIG_SERIAL_8250_NR_UARTS=32
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-# CONFIG_SERIAL_8250_ASPEED_VUART is not set
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-CONFIG_SERIAL_8250_RSA=y
-CONFIG_SERIAL_8250_FSL=y
-CONFIG_SERIAL_8250_DW=y
-CONFIG_SERIAL_8250_RT288X=y
-# CONFIG_SERIAL_8250_MOXA is not set
-CONFIG_SERIAL_OF_PLATFORM=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_AMBA_PL010 is not set
-CONFIG_SERIAL_AMBA_PL011=y
-CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST=y
-# CONFIG_SERIAL_KGDB_NMI is not set
-# CONFIG_SERIAL_MAX3100 is not set
-# CONFIG_SERIAL_MAX310X is not set
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_CONSOLE_POLL=y
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_MSM is not set
-# CONFIG_SERIAL_SCCNXP is not set
-# CONFIG_SERIAL_SC16IS7XX is not set
-# CONFIG_SERIAL_ALTERA_JTAGUART is not set
-# CONFIG_SERIAL_ALTERA_UART is not set
-# CONFIG_SERIAL_IFX6X60 is not set
-# CONFIG_SERIAL_XILINX_PS_UART is not set
-# CONFIG_SERIAL_ARC is not set
-# CONFIG_SERIAL_RP2 is not set
-# CONFIG_SERIAL_FSL_LPUART is not set
-# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
-# CONFIG_SERIAL_DEV_BUS is not set
-# CONFIG_TTY_PRINTK is not set
-CONFIG_HVC_DRIVER=y
-# CONFIG_HVC_DCC is not set
-CONFIG_VIRTIO_CONSOLE=m
-CONFIG_IPMI_HANDLER=m
-CONFIG_IPMI_DMI_DECODE=y
-# CONFIG_IPMI_PANIC_EVENT is not set
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_SI=m
-CONFIG_IPMI_SSIF=m
-CONFIG_IPMI_WATCHDOG=m
-CONFIG_IPMI_POWEROFF=m
-CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_TIMERIOMEM=m
-CONFIG_HW_RANDOM_VIRTIO=m
-CONFIG_HW_RANDOM_HISI=y
-CONFIG_HW_RANDOM_XGENE=y
-CONFIG_HW_RANDOM_CAVIUM=y
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# PCMCIA character devices
-#
-CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=8192
-CONFIG_TCG_TPM=m
-CONFIG_HW_RANDOM_TPM=y
-CONFIG_TCG_TIS_CORE=m
-# CONFIG_TCG_TIS is not set
-CONFIG_TCG_TIS_SPI=m
-# CONFIG_TCG_TIS_I2C_ATMEL is not set
-# CONFIG_TCG_TIS_I2C_INFINEON is not set
-# CONFIG_TCG_TIS_I2C_NUVOTON is not set
-CONFIG_TCG_ATMEL=m
-# CONFIG_TCG_INFINEON is not set
-CONFIG_TCG_CRB=m
-# CONFIG_TCG_VTPM_PROXY is not set
-# CONFIG_TCG_TIS_ST33ZP24_I2C is not set
-# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
-# CONFIG_DEVPORT is not set
-# CONFIG_XILLYBUS is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_COMPAT=y
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_MUX=m
-
-#
-# Multiplexer I2C Chip support
-#
-CONFIG_I2C_ARB_GPIO_CHALLENGE=m
-CONFIG_I2C_MUX_GPIO=m
-# CONFIG_I2C_MUX_GPMUX is not set
-# CONFIG_I2C_MUX_LTC4306 is not set
-CONFIG_I2C_MUX_PCA9541=m
-CONFIG_I2C_MUX_PCA954x=m
-CONFIG_I2C_MUX_PINCTRL=m
-# CONFIG_I2C_MUX_REG is not set
-# CONFIG_I2C_DEMUX_PINCTRL is not set
-CONFIG_I2C_MUX_MLXCPLD=m
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_SMBUS=m
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_ALGOPCA=m
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HIX5HD2 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_NFORCE2=m
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
-# ACPI drivers
-#
-# CONFIG_I2C_SCMI is not set
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-# CONFIG_I2C_CADENCE is not set
-# CONFIG_I2C_CBUS_GPIO is not set
-CONFIG_I2C_DESIGNWARE_CORE=m
-CONFIG_I2C_DESIGNWARE_PLATFORM=m
-# CONFIG_I2C_DESIGNWARE_SLAVE is not set
-# CONFIG_I2C_DESIGNWARE_PCI is not set
-# CONFIG_I2C_EMEV2 is not set
-CONFIG_I2C_GPIO=m
-# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
-# CONFIG_I2C_NOMADIK is not set
-# CONFIG_I2C_OCORES is not set
-CONFIG_I2C_PCA_PLATFORM=m
-CONFIG_I2C_QUP=m
-# CONFIG_I2C_RK3X is not set
-CONFIG_I2C_SIMTEC=m
-CONFIG_I2C_VERSATILE=m
-CONFIG_I2C_THUNDERX=m
-# CONFIG_I2C_XILINX is not set
-CONFIG_I2C_XLP9XX=m
-
-#
-# External I2C/SMBus adapter drivers
-#
-CONFIG_I2C_DIOLAN_U2C=m
-CONFIG_I2C_PARPORT_LIGHT=m
-# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
-# CONFIG_I2C_TAOS_EVM is not set
-CONFIG_I2C_TINY_USB=m
-
-#
-# Other I2C/SMBus bus drivers
-#
-CONFIG_I2C_XGENE_SLIMPRO=m
-CONFIG_I2C_STUB=m
-CONFIG_I2C_SLAVE=y
-CONFIG_I2C_SLAVE_EEPROM=m
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-CONFIG_SPI=y
-# CONFIG_SPI_DEBUG is not set
-CONFIG_SPI_MASTER=y
-# CONFIG_SPI_MEM is not set
-
-#
-# SPI Master Controller Drivers
-#
-# CONFIG_SPI_ALTERA is not set
-# CONFIG_SPI_AXI_SPI_ENGINE is not set
-# CONFIG_SPI_BITBANG is not set
-CONFIG_SPI_CADENCE=m
-CONFIG_SPI_DESIGNWARE=y
-CONFIG_SPI_DW_PCI=m
-# CONFIG_SPI_DW_MID_DMA is not set
-CONFIG_SPI_DW_MMIO=m
-# CONFIG_SPI_GPIO is not set
-# CONFIG_SPI_FSL_SPI is not set
-# CONFIG_SPI_OC_TINY is not set
-CONFIG_SPI_PL022=y
-# CONFIG_SPI_PXA2XX is not set
-# CONFIG_SPI_ROCKCHIP is not set
-CONFIG_SPI_QUP=y
-# CONFIG_SPI_SC18IS602 is not set
-# CONFIG_SPI_THUNDERX is not set
-# CONFIG_SPI_XCOMM is not set
-# CONFIG_SPI_XILINX is not set
-CONFIG_SPI_XLP=m
-# CONFIG_SPI_ZYNQMP_GQSPI is not set
-
-#
-# SPI Protocol Masters
-#
-# CONFIG_SPI_SPIDEV is not set
-# CONFIG_SPI_LOOPBACK_TEST is not set
-# CONFIG_SPI_TLE62X0 is not set
-# CONFIG_SPI_SLAVE is not set
-# CONFIG_SPMI is not set
-# CONFIG_HSI is not set
-CONFIG_PPS=y
-# CONFIG_PPS_DEBUG is not set
-
-#
-# PPS clients support
-#
-# CONFIG_PPS_CLIENT_KTIMER is not set
-CONFIG_PPS_CLIENT_LDISC=m
-CONFIG_PPS_CLIENT_GPIO=m
-
-#
-# PPS generators support
-#
-
-#
-# PTP clock support
-#
-CONFIG_PTP_1588_CLOCK=y
-CONFIG_DP83640_PHY=m
-CONFIG_PINCTRL=y
-CONFIG_PINMUX=y
-CONFIG_PINCONF=y
-CONFIG_GENERIC_PINCONF=y
-# CONFIG_DEBUG_PINCTRL is not set
-# CONFIG_PINCTRL_AMD is not set
-# CONFIG_PINCTRL_MCP23S08 is not set
-# CONFIG_PINCTRL_SINGLE is not set
-CONFIG_PINCTRL_MSM=y
-# CONFIG_PINCTRL_APQ8064 is not set
-# CONFIG_PINCTRL_APQ8084 is not set
-# CONFIG_PINCTRL_IPQ4019 is not set
-# CONFIG_PINCTRL_IPQ8064 is not set
-# CONFIG_PINCTRL_IPQ8074 is not set
-# CONFIG_PINCTRL_MSM8660 is not set
-# CONFIG_PINCTRL_MSM8960 is not set
-# CONFIG_PINCTRL_MDM9615 is not set
-# CONFIG_PINCTRL_MSM8X74 is not set
-# CONFIG_PINCTRL_MSM8916 is not set
-# CONFIG_PINCTRL_MSM8994 is not set
-# CONFIG_PINCTRL_MSM8996 is not set
-# CONFIG_PINCTRL_MSM8998 is not set
-CONFIG_PINCTRL_QDF2XXX=y
-# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set
-# CONFIG_PINCTRL_SDM845 is not set
-CONFIG_GPIOLIB=y
-CONFIG_GPIOLIB_FASTPATH_LIMIT=512
-CONFIG_OF_GPIO=y
-CONFIG_GPIO_ACPI=y
-CONFIG_GPIOLIB_IRQCHIP=y
-# CONFIG_DEBUG_GPIO is not set
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_GENERIC=m
-
-#
-# Memory mapped GPIO drivers
-#
-# CONFIG_GPIO_74XX_MMIO is not set
-# CONFIG_GPIO_ALTERA is not set
-CONFIG_GPIO_AMDPT=m
-# CONFIG_GPIO_DWAPB is not set
-# CONFIG_GPIO_EXAR is not set
-# CONFIG_GPIO_FTGPIO010 is not set
-CONFIG_GPIO_GENERIC_PLATFORM=m
-# CONFIG_GPIO_GRGPIO is not set
-# CONFIG_GPIO_HLWD is not set
-# CONFIG_GPIO_MB86S7X is not set
-# CONFIG_GPIO_MOCKUP is not set
-CONFIG_GPIO_PL061=y
-# CONFIG_GPIO_SYSCON is not set
-# CONFIG_GPIO_THUNDERX is not set
-CONFIG_GPIO_XGENE=y
-CONFIG_GPIO_XGENE_SB=m
-# CONFIG_GPIO_XILINX is not set
-CONFIG_GPIO_XLP=m
-
-#
-# I2C GPIO expanders
-#
-# CONFIG_GPIO_ADP5588 is not set
-# CONFIG_GPIO_ADNP is not set
-# CONFIG_GPIO_MAX7300 is not set
-# CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
-# CONFIG_GPIO_PCF857X is not set
-# CONFIG_GPIO_TPIC2810 is not set
-
-#
-# MFD GPIO expanders
-#
-
-#
-# PCI GPIO expanders
-#
-# CONFIG_GPIO_BT8XX is not set
-# CONFIG_GPIO_PCI_IDIO_16 is not set
-# CONFIG_GPIO_PCIE_IDIO_24 is not set
-# CONFIG_GPIO_RDC321X is not set
-
-#
-# SPI GPIO expanders
-#
-# CONFIG_GPIO_74X164 is not set
-# CONFIG_GPIO_MAX3191X is not set
-# CONFIG_GPIO_MAX7301 is not set
-# CONFIG_GPIO_MC33880 is not set
-# CONFIG_GPIO_PISOSR is not set
-# CONFIG_GPIO_XRA1403 is not set
-
-#
-# USB GPIO expanders
-#
-# CONFIG_W1 is not set
-# CONFIG_POWER_AVS is not set
-CONFIG_POWER_RESET=y
-# CONFIG_POWER_RESET_BRCMSTB is not set
-CONFIG_POWER_RESET_GPIO=y
-CONFIG_POWER_RESET_GPIO_RESTART=y
-CONFIG_POWER_RESET_HISI=y
-# CONFIG_POWER_RESET_MSM is not set
-# CONFIG_POWER_RESET_LTC2952 is not set
-CONFIG_POWER_RESET_RESTART=y
-CONFIG_POWER_RESET_VEXPRESS=y
-# CONFIG_POWER_RESET_XGENE is not set
-CONFIG_POWER_RESET_SYSCON=y
-# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
-# CONFIG_SYSCON_REBOOT_MODE is not set
-CONFIG_POWER_SUPPLY=y
-# CONFIG_POWER_SUPPLY_DEBUG is not set
-# CONFIG_PDA_POWER is not set
-# CONFIG_TEST_POWER is not set
-# CONFIG_CHARGER_ADP5061 is not set
-# CONFIG_BATTERY_DS2780 is not set
-# CONFIG_BATTERY_DS2781 is not set
-# CONFIG_BATTERY_DS2782 is not set
-# CONFIG_BATTERY_SBS is not set
-# CONFIG_CHARGER_SBS is not set
-# CONFIG_MANAGER_SBS is not set
-# CONFIG_BATTERY_BQ27XXX is not set
-# CONFIG_BATTERY_MAX17040 is not set
-# CONFIG_BATTERY_MAX17042 is not set
-# CONFIG_CHARGER_MAX8903 is not set
-# CONFIG_CHARGER_LP8727 is not set
-# CONFIG_CHARGER_GPIO is not set
-# CONFIG_CHARGER_LTC3651 is not set
-# CONFIG_CHARGER_DETECTOR_MAX14656 is not set
-# CONFIG_CHARGER_BQ2415X is not set
-# CONFIG_CHARGER_BQ24190 is not set
-# CONFIG_CHARGER_BQ24257 is not set
-# CONFIG_CHARGER_BQ24735 is not set
-# CONFIG_CHARGER_BQ25890 is not set
-CONFIG_CHARGER_SMB347=m
-# CONFIG_BATTERY_GAUGE_LTC2941 is not set
-# CONFIG_CHARGER_RT9455 is not set
-CONFIG_HWMON=y
-CONFIG_HWMON_VID=m
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Native drivers
-#
-CONFIG_SENSORS_AD7314=m
-CONFIG_SENSORS_AD7414=m
-CONFIG_SENSORS_AD7418=m
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM1026=m
-CONFIG_SENSORS_ADM1029=m
-CONFIG_SENSORS_ADM1031=m
-CONFIG_SENSORS_ADM9240=m
-CONFIG_SENSORS_ADT7X10=m
-CONFIG_SENSORS_ADT7310=m
-CONFIG_SENSORS_ADT7410=m
-CONFIG_SENSORS_ADT7411=m
-CONFIG_SENSORS_ADT7462=m
-CONFIG_SENSORS_ADT7470=m
-CONFIG_SENSORS_ADT7475=m
-CONFIG_SENSORS_ASC7621=m
-CONFIG_SENSORS_ARM_SCPI=m
-# CONFIG_SENSORS_ASPEED is not set
-CONFIG_SENSORS_ATXP1=m
-CONFIG_SENSORS_DS620=m
-CONFIG_SENSORS_DS1621=m
-# CONFIG_SENSORS_I5K_AMB is not set
-CONFIG_SENSORS_F71805F=m
-CONFIG_SENSORS_F71882FG=m
-CONFIG_SENSORS_F75375S=m
-# CONFIG_SENSORS_FTSTEUTATES is not set
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_G760A=m
-CONFIG_SENSORS_G762=m
-# CONFIG_SENSORS_GPIO_FAN is not set
-# CONFIG_SENSORS_HIH6130 is not set
-CONFIG_SENSORS_IBMAEM=m
-CONFIG_SENSORS_IBMPEX=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_JC42=m
-CONFIG_SENSORS_POWR1220=m
-CONFIG_SENSORS_LINEAGE=m
-CONFIG_SENSORS_LTC2945=m
-# CONFIG_SENSORS_LTC2990 is not set
-CONFIG_SENSORS_LTC4151=m
-CONFIG_SENSORS_LTC4215=m
-CONFIG_SENSORS_LTC4222=m
-CONFIG_SENSORS_LTC4245=m
-CONFIG_SENSORS_LTC4260=m
-CONFIG_SENSORS_LTC4261=m
-CONFIG_SENSORS_MAX1111=m
-CONFIG_SENSORS_MAX16065=m
-CONFIG_SENSORS_MAX1619=m
-CONFIG_SENSORS_MAX1668=m
-CONFIG_SENSORS_MAX197=m
-# CONFIG_SENSORS_MAX31722 is not set
-# CONFIG_SENSORS_MAX6621 is not set
-CONFIG_SENSORS_MAX6639=m
-CONFIG_SENSORS_MAX6642=m
-CONFIG_SENSORS_MAX6650=m
-CONFIG_SENSORS_MAX6697=m
-CONFIG_SENSORS_MAX31790=m
-CONFIG_SENSORS_MCP3021=m
-# CONFIG_SENSORS_TC654 is not set
-CONFIG_SENSORS_ADCXX=m
-CONFIG_SENSORS_LM63=m
-CONFIG_SENSORS_LM70=m
-CONFIG_SENSORS_LM73=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM77=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM83=m
-CONFIG_SENSORS_LM85=m
-CONFIG_SENSORS_LM87=m
-CONFIG_SENSORS_LM90=m
-CONFIG_SENSORS_LM92=m
-CONFIG_SENSORS_LM93=m
-CONFIG_SENSORS_LM95234=m
-CONFIG_SENSORS_LM95241=m
-CONFIG_SENSORS_LM95245=m
-CONFIG_SENSORS_PC87360=m
-CONFIG_SENSORS_PC87427=m
-CONFIG_SENSORS_NTC_THERMISTOR=m
-CONFIG_SENSORS_NCT6683=m
-CONFIG_SENSORS_NCT6775=m
-CONFIG_SENSORS_NCT7802=m
-CONFIG_SENSORS_NCT7904=m
-# CONFIG_SENSORS_NPCM7XX is not set
-CONFIG_SENSORS_PCF8591=m
-CONFIG_PMBUS=m
-CONFIG_SENSORS_PMBUS=m
-CONFIG_SENSORS_ADM1275=m
-# CONFIG_SENSORS_IBM_CFFPS is not set
-# CONFIG_SENSORS_IR35221 is not set
-CONFIG_SENSORS_LM25066=m
-CONFIG_SENSORS_LTC2978=m
-CONFIG_SENSORS_LTC3815=m
-CONFIG_SENSORS_MAX16064=m
-CONFIG_SENSORS_MAX20751=m
-# CONFIG_SENSORS_MAX31785 is not set
-CONFIG_SENSORS_MAX34440=m
-CONFIG_SENSORS_MAX8688=m
-CONFIG_SENSORS_TPS40422=m
-# CONFIG_SENSORS_TPS53679 is not set
-CONFIG_SENSORS_UCD9000=m
-CONFIG_SENSORS_UCD9200=m
-CONFIG_SENSORS_ZL6100=m
-CONFIG_SENSORS_PWM_FAN=m
-CONFIG_SENSORS_SHT15=m
-CONFIG_SENSORS_SHT21=m
-# CONFIG_SENSORS_SHT3x is not set
-CONFIG_SENSORS_SHTC1=m
-CONFIG_SENSORS_SIS5595=m
-CONFIG_SENSORS_DME1737=m
-CONFIG_SENSORS_EMC1403=m
-# CONFIG_SENSORS_EMC2103 is not set
-CONFIG_SENSORS_EMC6W201=m
-CONFIG_SENSORS_SMSC47M1=m
-CONFIG_SENSORS_SMSC47M192=m
-CONFIG_SENSORS_SMSC47B397=m
-CONFIG_SENSORS_SCH56XX_COMMON=m
-CONFIG_SENSORS_SCH5627=m
-CONFIG_SENSORS_SCH5636=m
-# CONFIG_SENSORS_STTS751 is not set
-# CONFIG_SENSORS_SMM665 is not set
-CONFIG_SENSORS_ADC128D818=m
-CONFIG_SENSORS_ADS1015=m
-CONFIG_SENSORS_ADS7828=m
-CONFIG_SENSORS_ADS7871=m
-CONFIG_SENSORS_AMC6821=m
-CONFIG_SENSORS_INA209=m
-CONFIG_SENSORS_INA2XX=m
-# CONFIG_SENSORS_INA3221 is not set
-CONFIG_SENSORS_TC74=m
-CONFIG_SENSORS_THMC50=m
-CONFIG_SENSORS_TMP102=m
-CONFIG_SENSORS_TMP103=m
-# CONFIG_SENSORS_TMP108 is not set
-CONFIG_SENSORS_TMP401=m
-CONFIG_SENSORS_TMP421=m
-CONFIG_SENSORS_VEXPRESS=m
-CONFIG_SENSORS_VIA686A=m
-CONFIG_SENSORS_VT1211=m
-CONFIG_SENSORS_VT8231=m
-# CONFIG_SENSORS_W83773G is not set
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_W83791D=m
-CONFIG_SENSORS_W83792D=m
-CONFIG_SENSORS_W83793=m
-CONFIG_SENSORS_W83795=m
-# CONFIG_SENSORS_W83795_FANCTRL is not set
-CONFIG_SENSORS_W83L785TS=m
-CONFIG_SENSORS_W83L786NG=m
-CONFIG_SENSORS_W83627HF=m
-CONFIG_SENSORS_W83627EHF=m
-CONFIG_SENSORS_XGENE=m
-
-#
-# ACPI drivers
-#
-CONFIG_SENSORS_ACPI_POWER=m
-CONFIG_THERMAL=y
-# CONFIG_THERMAL_STATISTICS is not set
-CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
-CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_OF=y
-# CONFIG_THERMAL_WRITABLE_TRIPS is not set
-CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
-# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
-# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
-# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
-CONFIG_THERMAL_GOV_FAIR_SHARE=y
-CONFIG_THERMAL_GOV_STEP_WISE=y
-# CONFIG_THERMAL_GOV_BANG_BANG is not set
-CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
-CONFIG_CPU_THERMAL=y
-# CONFIG_THERMAL_EMULATION is not set
-CONFIG_HISI_THERMAL=y
-# CONFIG_QORIQ_THERMAL is not set
-
-#
-# ACPI INT340X thermal drivers
-#
-
-#
-# Qualcomm thermal drivers
-#
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_CORE=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
-CONFIG_WATCHDOG_SYSFS=y
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_GPIO_WATCHDOG=m
-# CONFIG_WDAT_WDT is not set
-# CONFIG_XILINX_WATCHDOG is not set
-# CONFIG_ZIIRAVE_WATCHDOG is not set
-CONFIG_ARM_SP805_WATCHDOG=m
-CONFIG_ARM_SBSA_WATCHDOG=m
-# CONFIG_CADENCE_WATCHDOG is not set
-# CONFIG_DW_WATCHDOG is not set
-# CONFIG_MAX63XX_WATCHDOG is not set
-# CONFIG_QCOM_WDT is not set
-CONFIG_ALIM7101_WDT=m
-CONFIG_I6300ESB_WDT=m
-# CONFIG_MEN_A21_WDT is not set
-
-#
-# PCI-based Watchdog Cards
-#
-CONFIG_PCIPCWATCHDOG=m
-CONFIG_WDTPCI=m
-
-#
-# USB-based Watchdog Cards
-#
-CONFIG_USBPCWATCHDOG=m
-
-#
-# Watchdog Pretimeout Governors
-#
-# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-CONFIG_BCMA_POSSIBLE=y
-CONFIG_BCMA=m
-CONFIG_BCMA_HOST_PCI_POSSIBLE=y
-CONFIG_BCMA_HOST_PCI=y
-# CONFIG_BCMA_HOST_SOC is not set
-CONFIG_BCMA_DRIVER_PCI=y
-CONFIG_BCMA_DRIVER_GMAC_CMN=y
-CONFIG_BCMA_DRIVER_GPIO=y
-# CONFIG_BCMA_DEBUG is not set
-
-#
-# Multifunction device drivers
-#
-CONFIG_MFD_CORE=m
-# CONFIG_MFD_ACT8945A is not set
-# CONFIG_MFD_ATMEL_FLEXCOM is not set
-# CONFIG_MFD_ATMEL_HLCDC is not set
-# CONFIG_MFD_BCM590XX is not set
-# CONFIG_MFD_BD9571MWV is not set
-# CONFIG_MFD_AXP20X_I2C is not set
-# CONFIG_MFD_CROS_EC is not set
-# CONFIG_MFD_MADERA is not set
-# CONFIG_MFD_DA9052_SPI is not set
-# CONFIG_MFD_DA9062 is not set
-# CONFIG_MFD_DA9063 is not set
-# CONFIG_MFD_DA9150 is not set
-# CONFIG_MFD_DLN2 is not set
-# CONFIG_MFD_MC13XXX_SPI is not set
-# CONFIG_MFD_MC13XXX_I2C is not set
-# CONFIG_MFD_HI6421_PMIC is not set
-# CONFIG_MFD_HI655X_PMIC is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_LPC_ICH is not set
-# CONFIG_LPC_SCH is not set
-# CONFIG_MFD_JANZ_CMODIO is not set
-# CONFIG_MFD_KEMPLD is not set
-# CONFIG_MFD_88PM800 is not set
-# CONFIG_MFD_88PM805 is not set
-# CONFIG_MFD_MAX14577 is not set
-# CONFIG_MFD_MAX77686 is not set
-# CONFIG_MFD_MAX77693 is not set
-# CONFIG_MFD_MAX8907 is not set
-# CONFIG_MFD_MT6397 is not set
-# CONFIG_MFD_MENF21BMC is not set
-# CONFIG_EZX_PCAP is not set
-# CONFIG_MFD_CPCAP is not set
-# CONFIG_MFD_VIPERBOARD is not set
-# CONFIG_MFD_RETU is not set
-# CONFIG_MFD_PCF50633 is not set
-# CONFIG_MFD_QCOM_RPM is not set
-# CONFIG_MFD_RDC321X is not set
-# CONFIG_MFD_RT5033 is not set
-# CONFIG_MFD_RK808 is not set
-# CONFIG_MFD_RN5T618 is not set
-# CONFIG_MFD_SI476X_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_SKY81452 is not set
-# CONFIG_ABX500_CORE is not set
-# CONFIG_MFD_STMPE is not set
-CONFIG_MFD_SYSCON=y
-# CONFIG_MFD_TI_AM335X_TSCADC is not set
-# CONFIG_MFD_LP3943 is not set
-# CONFIG_MFD_TI_LMU is not set
-# CONFIG_TPS6105X is not set
-# CONFIG_TPS65010 is not set
-# CONFIG_TPS6507X is not set
-# CONFIG_MFD_TPS65086 is not set
-# CONFIG_MFD_TPS65217 is not set
-# CONFIG_MFD_TI_LP873X is not set
-# CONFIG_MFD_TI_LP87565 is not set
-# CONFIG_MFD_TPS65218 is not set
-# CONFIG_MFD_TPS65912_I2C is not set
-# CONFIG_MFD_TPS65912_SPI is not set
-# CONFIG_MFD_WL1273_CORE is not set
-# CONFIG_MFD_LM3533 is not set
-# CONFIG_MFD_VX855 is not set
-# CONFIG_MFD_ARIZONA_I2C is not set
-# CONFIG_MFD_ARIZONA_SPI is not set
-# CONFIG_MFD_WM831X_SPI is not set
-# CONFIG_MFD_WM8994 is not set
-# CONFIG_MFD_VEXPRESS_SYSREG is not set
-# CONFIG_REGULATOR is not set
-# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_SUPPORT is not set
-
-#
-# Graphics support
-#
-CONFIG_VGA_ARB=y
-CONFIG_VGA_ARB_MAX_GPUS=64
-CONFIG_DRM=m
-CONFIG_DRM_DP_AUX_CHARDEV=y
-# CONFIG_DRM_DEBUG_SELFTEST is not set
-CONFIG_DRM_KMS_HELPER=m
-CONFIG_DRM_KMS_FB_HELPER=y
-CONFIG_DRM_FBDEV_EMULATION=y
-CONFIG_DRM_FBDEV_OVERALLOC=100
-# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set
-CONFIG_DRM_LOAD_EDID_FIRMWARE=y
-# CONFIG_DRM_DP_CEC is not set
-CONFIG_DRM_TTM=m
-CONFIG_DRM_VM=y
-CONFIG_DRM_SCHED=m
-
-#
-# I2C encoder or helper chips
-#
-CONFIG_DRM_I2C_CH7006=m
-# CONFIG_DRM_I2C_SIL164 is not set
-CONFIG_DRM_I2C_NXP_TDA998X=m
-# CONFIG_DRM_I2C_NXP_TDA9950 is not set
-# CONFIG_DRM_HDLCD is not set
-# CONFIG_DRM_MALI_DISPLAY is not set
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_RADEON_USERPTR=y
-CONFIG_DRM_AMDGPU=m
-# CONFIG_DRM_AMDGPU_SI is not set
-CONFIG_DRM_AMDGPU_CIK=y
-CONFIG_DRM_AMDGPU_USERPTR=y
-# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set
-
-#
-# ACP (Audio CoProcessor) Configuration
-#
-# CONFIG_DRM_AMD_ACP is not set
-
-#
-# Display Engine Configuration
-#
-CONFIG_DRM_AMD_DC=y
-# CONFIG_DEBUG_KERNEL_DC is not set
-
-#
-# AMD Library routines
-#
-CONFIG_CHASH=m
-# CONFIG_CHASH_STATS is not set
-# CONFIG_CHASH_SELFTEST is not set
-CONFIG_DRM_NOUVEAU=m
-CONFIG_NOUVEAU_DEBUG=5
-CONFIG_NOUVEAU_DEBUG_DEFAULT=3
-# CONFIG_NOUVEAU_DEBUG_MMU is not set
-CONFIG_DRM_NOUVEAU_BACKLIGHT=y
-# CONFIG_DRM_VGEM is not set
-# CONFIG_DRM_VKMS is not set
-CONFIG_DRM_UDL=m
-CONFIG_DRM_AST=m
-CONFIG_DRM_MGAG200=m
-CONFIG_DRM_CIRRUS_QEMU=m
-# CONFIG_DRM_RCAR_DW_HDMI is not set
-# CONFIG_DRM_RCAR_LVDS is not set
-CONFIG_DRM_QXL=m
-CONFIG_DRM_BOCHS=m
-CONFIG_DRM_VIRTIO_GPU=m
-# CONFIG_DRM_MSM is not set
-CONFIG_DRM_PANEL=y
-
-#
-# Display Panels
-#
-# CONFIG_DRM_PANEL_ARM_VERSATILE is not set
-# CONFIG_DRM_PANEL_LVDS is not set
-# CONFIG_DRM_PANEL_SIMPLE is not set
-# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set
-# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
-# CONFIG_DRM_PANEL_LG_LG4573 is not set
-# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
-# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set
-# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set
-CONFIG_DRM_BRIDGE=y
-CONFIG_DRM_PANEL_BRIDGE=y
-
-#
-# Display Interface Bridges
-#
-# CONFIG_DRM_ANALOGIX_ANX78XX is not set
-# CONFIG_DRM_CDNS_DSI is not set
-# CONFIG_DRM_DUMB_VGA_DAC is not set
-# CONFIG_DRM_LVDS_ENCODER is not set
-# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set
-# CONFIG_DRM_NXP_PTN3460 is not set
-# CONFIG_DRM_PARADE_PS8622 is not set
-# CONFIG_DRM_SIL_SII8620 is not set
-# CONFIG_DRM_SII902X is not set
-# CONFIG_DRM_SII9234 is not set
-# CONFIG_DRM_THINE_THC63LVD1024 is not set
-# CONFIG_DRM_TOSHIBA_TC358767 is not set
-# CONFIG_DRM_TI_TFP410 is not set
-# CONFIG_DRM_I2C_ADV7511 is not set
-# CONFIG_DRM_ARCPGU is not set
-CONFIG_DRM_HISI_HIBMC=m
-# CONFIG_DRM_HISI_KIRIN is not set
-# CONFIG_DRM_MXSFB is not set
-# CONFIG_DRM_TINYDRM is not set
-# CONFIG_DRM_PL111 is not set
-# CONFIG_DRM_LEGACY is not set
-CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
-
-#
-# Frame buffer Devices
-#
-CONFIG_FB=y
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB_CMDLINE=y
-CONFIG_FB_NOTIFY=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SYS_FILLRECT=m
-CONFIG_FB_SYS_COPYAREA=m
-CONFIG_FB_SYS_IMAGEBLIT=m
-# CONFIG_FB_FOREIGN_ENDIAN is not set
-CONFIG_FB_SYS_FOPS=m
-CONFIG_FB_DEFERRED_IO=y
-CONFIG_FB_BACKLIGHT=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-
-#
-# Frame buffer hardware drivers
-#
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_ARMCLCD=y
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_UVESA is not set
-CONFIG_FB_EFI=y
-# CONFIG_FB_OPENCORES is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_I740 is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_VT8623 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_ARK is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_CARMINE is not set
-# CONFIG_FB_SMSCUFX is not set
-# CONFIG_FB_UDL is not set
-# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FB_METRONOME is not set
-# CONFIG_FB_MB862XX is not set
-# CONFIG_FB_BROADSHEET is not set
-CONFIG_FB_SIMPLE=y
-CONFIG_FB_SSD1307=m
-# CONFIG_FB_SM712 is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=m
-# CONFIG_LCD_L4F00242T03 is not set
-# CONFIG_LCD_LMS283GF05 is not set
-# CONFIG_LCD_LTV350QV is not set
-# CONFIG_LCD_ILI922X is not set
-# CONFIG_LCD_ILI9320 is not set
-# CONFIG_LCD_TDO24M is not set
-# CONFIG_LCD_VGG2432A4 is not set
-CONFIG_LCD_PLATFORM=m
-# CONFIG_LCD_S6E63M0 is not set
-# CONFIG_LCD_LD9040 is not set
-# CONFIG_LCD_AMS369FG06 is not set
-# CONFIG_LCD_LMS501KF03 is not set
-# CONFIG_LCD_HX8357 is not set
-# CONFIG_LCD_OTM3225A is not set
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_BACKLIGHT_PWM=m
-# CONFIG_BACKLIGHT_PM8941_WLED is not set
-# CONFIG_BACKLIGHT_ADP8860 is not set
-# CONFIG_BACKLIGHT_ADP8870 is not set
-# CONFIG_BACKLIGHT_LM3630A is not set
-# CONFIG_BACKLIGHT_LM3639 is not set
-CONFIG_BACKLIGHT_LP855X=m
-CONFIG_BACKLIGHT_GPIO=m
-# CONFIG_BACKLIGHT_LV5207LP is not set
-# CONFIG_BACKLIGHT_BD6107 is not set
-# CONFIG_BACKLIGHT_ARCXCNN is not set
-CONFIG_VIDEOMODE_HELPERS=y
-CONFIG_HDMI=y
-
-#
-# Console display driver support
-#
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_DUMMY_CONSOLE_COLUMNS=80
-CONFIG_DUMMY_CONSOLE_ROWS=25
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
-# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_SOUND=m
-# CONFIG_SND is not set
-
-#
-# HID support
-#
-CONFIG_HID=y
-CONFIG_HID_BATTERY_STRENGTH=y
-CONFIG_HIDRAW=y
-CONFIG_UHID=m
-CONFIG_HID_GENERIC=y
-
-#
-# Special HID drivers
-#
-CONFIG_HID_A4TECH=y
-# CONFIG_HID_ACCUTOUCH is not set
-CONFIG_HID_ACRUX=m
-# CONFIG_HID_ACRUX_FF is not set
-CONFIG_HID_APPLE=y
-CONFIG_HID_APPLEIR=m
-# CONFIG_HID_ASUS is not set
-CONFIG_HID_AUREAL=m
-CONFIG_HID_BELKIN=y
-CONFIG_HID_BETOP_FF=m
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CORSAIR=m
-# CONFIG_HID_COUGAR is not set
-# CONFIG_HID_CMEDIA is not set
-# CONFIG_HID_CP2112 is not set
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_DRAGONRISE=m
-# CONFIG_DRAGONRISE_FF is not set
-# CONFIG_HID_EMS_FF is not set
-# CONFIG_HID_ELAN is not set
-CONFIG_HID_ELECOM=m
-CONFIG_HID_ELO=m
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GEMBIRD=m
-CONFIG_HID_GFRM=m
-CONFIG_HID_HOLTEK=m
-# CONFIG_HOLTEK_FF is not set
-# CONFIG_HID_GOOGLE_HAMMER is not set
-CONFIG_HID_GT683R=m
-CONFIG_HID_KEYTOUCH=m
-CONFIG_HID_KYE=m
-CONFIG_HID_UCLOGIC=m
-CONFIG_HID_WALTOP=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_ICADE=m
-CONFIG_HID_ITE=y
-# CONFIG_HID_JABRA is not set
-CONFIG_HID_TWINHAN=m
-CONFIG_HID_KENSINGTON=y
-CONFIG_HID_LCPOWER=m
-CONFIG_HID_LED=m
-CONFIG_HID_LENOVO=m
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_LOGITECH_DJ=m
-CONFIG_HID_LOGITECH_HIDPP=m
-# CONFIG_LOGITECH_FF is not set
-# CONFIG_LOGIRUMBLEPAD2_FF is not set
-# CONFIG_LOGIG940_FF is not set
-# CONFIG_LOGIWHEELS_FF is not set
-CONFIG_HID_MAGICMOUSE=y
-# CONFIG_HID_MAYFLASH is not set
-# CONFIG_HID_REDRAGON is not set
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_MULTITOUCH=m
-# CONFIG_HID_NTI is not set
-CONFIG_HID_NTRIG=y
-CONFIG_HID_ORTEK=m
-CONFIG_HID_PANTHERLORD=m
-# CONFIG_PANTHERLORD_FF is not set
-CONFIG_HID_PENMOUNT=m
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_PICOLCD=m
-CONFIG_HID_PICOLCD_FB=y
-CONFIG_HID_PICOLCD_BACKLIGHT=y
-CONFIG_HID_PICOLCD_LCD=y
-CONFIG_HID_PICOLCD_LEDS=y
-CONFIG_HID_PLANTRONICS=m
-CONFIG_HID_PRIMAX=m
-# CONFIG_HID_RETRODE is not set
-CONFIG_HID_ROCCAT=m
-CONFIG_HID_SAITEK=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SONY=m
-CONFIG_SONY_FF=y
-CONFIG_HID_SPEEDLINK=m
-# CONFIG_HID_STEAM is not set
-CONFIG_HID_STEELSERIES=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_HID_RMI=m
-CONFIG_HID_GREENASIA=m
-# CONFIG_GREENASIA_FF is not set
-CONFIG_HID_SMARTJOYPLUS=m
-# CONFIG_SMARTJOYPLUS_FF is not set
-CONFIG_HID_TIVO=m
-CONFIG_HID_TOPSEED=m
-CONFIG_HID_THINGM=m
-CONFIG_HID_THRUSTMASTER=m
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_HID_UDRAW_PS3 is not set
-CONFIG_HID_WACOM=m
-CONFIG_HID_WIIMOTE=m
-CONFIG_HID_XINMO=m
-CONFIG_HID_ZEROPLUS=m
-# CONFIG_ZEROPLUS_FF is not set
-CONFIG_HID_ZYDACRON=m
-CONFIG_HID_SENSOR_HUB=m
-# CONFIG_HID_SENSOR_CUSTOM_SENSOR is not set
-# CONFIG_HID_ALPS is not set
-
-#
-# USB HID support
-#
-CONFIG_USB_HID=y
-CONFIG_HID_PID=y
-CONFIG_USB_HIDDEV=y
-
-#
-# I2C HID support
-#
-CONFIG_I2C_HID=m
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_COMMON=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB=y
-CONFIG_USB_PCI=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEFAULT_PERSIST=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_LEDS_TRIGGER_USBPORT=m
-CONFIG_USB_MON=y
-CONFIG_USB_WUSB=m
-CONFIG_USB_WUSB_CBAF=m
-# CONFIG_USB_WUSB_CBAF_DEBUG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_XHCI_HCD=y
-# CONFIG_USB_XHCI_DBGCAP is not set
-CONFIG_USB_XHCI_PCI=y
-CONFIG_USB_XHCI_PLATFORM=m
-# CONFIG_USB_XHCI_HISTB is not set
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
-CONFIG_USB_EHCI_PCI=y
-CONFIG_USB_EHCI_HCD_PLATFORM=y
-# CONFIG_USB_OXU210HP_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_FOTG210_HCD is not set
-# CONFIG_USB_MAX3421_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PCI=y
-# CONFIG_USB_OHCI_HCD_PLATFORM is not set
-CONFIG_USB_UHCI_HCD=y
-# CONFIG_USB_U132_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-# CONFIG_USB_R8A66597_HCD is not set
-# CONFIG_USB_WHCI_HCD is not set
-CONFIG_USB_HWA_HCD=m
-# CONFIG_USB_HCD_BCMA is not set
-# CONFIG_USB_HCD_TEST_MODE is not set
-
-#
-# USB Device Class drivers
-#
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_WDM=m
-CONFIG_USB_TMC=m
-
-#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
-#
-
-#
-# also be needed; see USB_STORAGE Help for more info
-#
-CONFIG_USB_STORAGE=m
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_REALTEK=m
-CONFIG_REALTEK_AUTOPM=y
-CONFIG_USB_STORAGE_DATAFAB=m
-CONFIG_USB_STORAGE_FREECOM=m
-CONFIG_USB_STORAGE_ISD200=m
-CONFIG_USB_STORAGE_USBAT=m
-CONFIG_USB_STORAGE_SDDR09=m
-CONFIG_USB_STORAGE_SDDR55=m
-CONFIG_USB_STORAGE_JUMPSHOT=m
-CONFIG_USB_STORAGE_ALAUDA=m
-CONFIG_USB_STORAGE_ONETOUCH=m
-CONFIG_USB_STORAGE_KARMA=m
-CONFIG_USB_STORAGE_CYPRESS_ATACB=m
-CONFIG_USB_STORAGE_ENE_UB6250=m
-CONFIG_USB_UAS=m
-
-#
-# USB Imaging devices
-#
-CONFIG_USB_MDC800=m
-CONFIG_USB_MICROTEK=m
-# CONFIG_USBIP_CORE is not set
-# CONFIG_USB_MUSB_HDRC is not set
-# CONFIG_USB_DWC3 is not set
-# CONFIG_USB_DWC2 is not set
-# CONFIG_USB_CHIPIDEA is not set
-# CONFIG_USB_ISP1760 is not set
-
-#
-# USB port drivers
-#
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_SIMPLE=m
-CONFIG_USB_SERIAL_AIRCABLE=m
-CONFIG_USB_SERIAL_ARK3116=m
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_CH341=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_CP210X=m
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-# CONFIG_USB_SERIAL_F81232 is not set
-# CONFIG_USB_SERIAL_F8153X is not set
-CONFIG_USB_SERIAL_GARMIN=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_IUU=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_MCT_U232=m
-# CONFIG_USB_SERIAL_METRO is not set
-CONFIG_USB_SERIAL_MOS7720=m
-CONFIG_USB_SERIAL_MOS7840=m
-# CONFIG_USB_SERIAL_MXUPORT is not set
-CONFIG_USB_SERIAL_NAVMAN=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_OTI6858=m
-CONFIG_USB_SERIAL_QCAUX=m
-CONFIG_USB_SERIAL_QUALCOMM=m
-CONFIG_USB_SERIAL_SPCP8X5=m
-CONFIG_USB_SERIAL_SAFE=m
-CONFIG_USB_SERIAL_SAFE_PADDED=y
-CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-CONFIG_USB_SERIAL_SYMBOL=m
-CONFIG_USB_SERIAL_TI=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_WWAN=m
-CONFIG_USB_SERIAL_OPTION=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_SERIAL_OPTICON=m
-CONFIG_USB_SERIAL_XSENS_MT=m
-# CONFIG_USB_SERIAL_WISHBONE is not set
-CONFIG_USB_SERIAL_SSU100=m
-CONFIG_USB_SERIAL_QT2=m
-# CONFIG_USB_SERIAL_UPD78F0730 is not set
-CONFIG_USB_SERIAL_DEBUG=m
-
-#
-# USB Miscellaneous drivers
-#
-CONFIG_USB_EMI62=m
-CONFIG_USB_EMI26=m
-CONFIG_USB_ADUTUX=m
-CONFIG_USB_SEVSEG=m
-# CONFIG_USB_RIO500 is not set
-CONFIG_USB_LEGOTOWER=m
-CONFIG_USB_LCD=m
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-CONFIG_USB_IDMOUSE=m
-CONFIG_USB_FTDI_ELAN=m
-CONFIG_USB_APPLEDISPLAY=m
-CONFIG_USB_SISUSBVGA=m
-CONFIG_USB_SISUSBVGA_CON=y
-CONFIG_USB_LD=m
-# CONFIG_USB_TRANCEVIBRATOR is not set
-CONFIG_USB_IOWARRIOR=m
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_EHSET_TEST_FIXTURE is not set
-CONFIG_USB_ISIGHTFW=m
-# CONFIG_USB_YUREX is not set
-CONFIG_USB_EZUSB_FX2=m
-# CONFIG_USB_HUB_USB251XB is not set
-CONFIG_USB_HSIC_USB3503=m
-# CONFIG_USB_HSIC_USB4604 is not set
-# CONFIG_USB_LINK_LAYER_TEST is not set
-CONFIG_USB_CHAOSKEY=m
-CONFIG_USB_ATM=m
-# CONFIG_USB_SPEEDTOUCH is not set
-CONFIG_USB_CXACRU=m
-CONFIG_USB_UEAGLEATM=m
-CONFIG_USB_XUSBATM=m
-
-#
-# USB Physical Layer drivers
-#
-# CONFIG_NOP_USB_XCEIV is not set
-# CONFIG_USB_GPIO_VBUS is not set
-# CONFIG_USB_ISP1301 is not set
-# CONFIG_USB_ULPI is not set
-# CONFIG_USB_GADGET is not set
-CONFIG_TYPEC=y
-# CONFIG_TYPEC_TCPM is not set
-CONFIG_TYPEC_UCSI=y
-CONFIG_UCSI_ACPI=y
-# CONFIG_TYPEC_TPS6598X is not set
-
-#
-# USB Type-C Multiplexer/DeMultiplexer Switch support
-#
-# CONFIG_TYPEC_MUX_PI3USB30532 is not set
-
-#
-# USB Type-C Alternate Mode drivers
-#
-# CONFIG_TYPEC_DP_ALTMODE is not set
-# CONFIG_USB_ROLE_SWITCH is not set
-CONFIG_USB_LED_TRIG=y
-CONFIG_USB_ULPI_BUS=m
-CONFIG_UWB=m
-CONFIG_UWB_HWA=m
-CONFIG_UWB_WHCI=m
-CONFIG_UWB_I1480U=m
-CONFIG_MMC=m
-CONFIG_PWRSEQ_EMMC=m
-CONFIG_PWRSEQ_SIMPLE=m
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_BLOCK_MINORS=8
-CONFIG_SDIO_UART=m
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD/SDIO Host Controller Drivers
-#
-# CONFIG_MMC_DEBUG is not set
-CONFIG_MMC_ARMMMCI=m
-CONFIG_MMC_SDHCI=m
-CONFIG_MMC_SDHCI_PCI=m
-CONFIG_MMC_RICOH_MMC=y
-CONFIG_MMC_SDHCI_ACPI=m
-CONFIG_MMC_SDHCI_PLTFM=m
-# CONFIG_MMC_SDHCI_OF_ARASAN is not set
-# CONFIG_MMC_SDHCI_OF_AT91 is not set
-# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set
-CONFIG_MMC_SDHCI_CADENCE=m
-# CONFIG_MMC_SDHCI_F_SDH30 is not set
-# CONFIG_MMC_SDHCI_MSM is not set
-CONFIG_MMC_TIFM_SD=m
-CONFIG_MMC_SPI=m
-CONFIG_MMC_CB710=m
-CONFIG_MMC_VIA_SDMMC=m
-CONFIG_MMC_DW=m
-CONFIG_MMC_DW_PLTFM=m
-CONFIG_MMC_DW_BLUEFIELD=m
-# CONFIG_MMC_DW_EXYNOS is not set
-# CONFIG_MMC_DW_HI3798CV200 is not set
-# CONFIG_MMC_DW_K3 is not set
-# CONFIG_MMC_DW_PCI is not set
-CONFIG_MMC_VUB300=m
-CONFIG_MMC_USHC=m
-# CONFIG_MMC_USDHI6ROL0 is not set
-CONFIG_MMC_CQHCI=m
-CONFIG_MMC_TOSHIBA_PCI=m
-CONFIG_MMC_MTK=m
-CONFIG_MMC_SDHCI_XENON=m
-# CONFIG_MMC_SDHCI_OMAP is not set
-CONFIG_MEMSTICK=m
-# CONFIG_MEMSTICK_DEBUG is not set
-
-#
-# MemoryStick drivers
-#
-# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
-CONFIG_MSPRO_BLOCK=m
-# CONFIG_MS_BLOCK is not set
-
-#
-# MemoryStick Host Controller Drivers
-#
-CONFIG_MEMSTICK_TIFM_MS=m
-CONFIG_MEMSTICK_JMICRON_38X=m
-CONFIG_MEMSTICK_R592=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_CLASS_FLASH=m
-# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
-
-#
-# LED drivers
-#
-# CONFIG_LEDS_AAT1290 is not set
-# CONFIG_LEDS_AS3645A is not set
-# CONFIG_LEDS_BCM6328 is not set
-# CONFIG_LEDS_BCM6358 is not set
-# CONFIG_LEDS_CR0014114 is not set
-CONFIG_LEDS_LM3530=m
-# CONFIG_LEDS_LM3642 is not set
-# CONFIG_LEDS_LM3692X is not set
-# CONFIG_LEDS_LM3601X is not set
-# CONFIG_LEDS_PCA9532 is not set
-# CONFIG_LEDS_GPIO is not set
-CONFIG_LEDS_LP3944=m
-# CONFIG_LEDS_LP3952 is not set
-# CONFIG_LEDS_LP5521 is not set
-# CONFIG_LEDS_LP5523 is not set
-# CONFIG_LEDS_LP5562 is not set
-# CONFIG_LEDS_LP8501 is not set
-# CONFIG_LEDS_LP8860 is not set
-# CONFIG_LEDS_PCA955X is not set
-# CONFIG_LEDS_PCA963X is not set
-# CONFIG_LEDS_DAC124S085 is not set
-# CONFIG_LEDS_PWM is not set
-# CONFIG_LEDS_BD2802 is not set
-CONFIG_LEDS_LT3593=m
-# CONFIG_LEDS_TCA6507 is not set
-# CONFIG_LEDS_TLC591XX is not set
-# CONFIG_LEDS_LM355x is not set
-# CONFIG_LEDS_KTD2692 is not set
-# CONFIG_LEDS_IS31FL319X is not set
-# CONFIG_LEDS_IS31FL32XX is not set
-
-#
-# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
-#
-CONFIG_LEDS_BLINKM=m
-# CONFIG_LEDS_SYSCON is not set
-# CONFIG_LEDS_MLXREG is not set
-# CONFIG_LEDS_USER is not set
-
-#
-# LED Triggers
-#
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=m
-CONFIG_LEDS_TRIGGER_ONESHOT=m
-# CONFIG_LEDS_TRIGGER_DISK is not set
-# CONFIG_LEDS_TRIGGER_MTD is not set
-CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-CONFIG_LEDS_TRIGGER_BACKLIGHT=m
-# CONFIG_LEDS_TRIGGER_CPU is not set
-# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
-CONFIG_LEDS_TRIGGER_GPIO=m
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
-
-#
-# iptables trigger is under Netfilter config (LED target)
-#
-CONFIG_LEDS_TRIGGER_TRANSIENT=m
-CONFIG_LEDS_TRIGGER_CAMERA=m
-# CONFIG_LEDS_TRIGGER_PANIC is not set
-# CONFIG_LEDS_TRIGGER_NETDEV is not set
-# CONFIG_ACCESSIBILITY is not set
-CONFIG_INFINIBAND=m
-CONFIG_INFINIBAND_USER_MAD=m
-CONFIG_INFINIBAND_USER_ACCESS=m
-# CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI is not set
-CONFIG_INFINIBAND_USER_MEM=y
-CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
-CONFIG_INFINIBAND_ADDR_TRANS=y
-CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y
-# CONFIG_INFINIBAND_MTHCA is not set
-# CONFIG_INFINIBAND_QIB is not set
-CONFIG_INFINIBAND_CXGB4=m
-CONFIG_INFINIBAND_I40IW=m
-CONFIG_MLX4_INFINIBAND=m
-CONFIG_MLX5_INFINIBAND=m
-# CONFIG_INFINIBAND_NES is not set
-# CONFIG_INFINIBAND_OCRDMA is not set
-CONFIG_INFINIBAND_HNS=m
-CONFIG_INFINIBAND_HNS_HIP06=m
-CONFIG_INFINIBAND_HNS_HIP08=m
-CONFIG_INFINIBAND_IPOIB=m
-CONFIG_INFINIBAND_IPOIB_CM=y
-CONFIG_INFINIBAND_IPOIB_DEBUG=y
-# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
-CONFIG_INFINIBAND_SRP=m
-CONFIG_INFINIBAND_SRPT=m
-CONFIG_INFINIBAND_ISER=m
-CONFIG_INFINIBAND_ISERT=m
-CONFIG_INFINIBAND_RDMAVT=m
-CONFIG_RDMA_RXE=m
-CONFIG_INFINIBAND_QEDR=m
-CONFIG_INFINIBAND_BNXT_RE=m
-CONFIG_EDAC_SUPPORT=y
-CONFIG_EDAC=y
-CONFIG_EDAC_LEGACY_SYSFS=y
-# CONFIG_EDAC_DEBUG is not set
-CONFIG_EDAC_GHES=y
-CONFIG_EDAC_THUNDERX=m
-CONFIG_EDAC_XGENE=m
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-# CONFIG_RTC_SYSTOHC is not set
-# CONFIG_RTC_DEBUG is not set
-CONFIG_RTC_NVMEM=y
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-# CONFIG_RTC_DRV_TEST is not set
-
-#
-# I2C RTC drivers
-#
-CONFIG_RTC_DRV_ABB5ZES3=m
-CONFIG_RTC_DRV_ABX80X=m
-CONFIG_RTC_DRV_DS1307=m
-# CONFIG_RTC_DRV_DS1307_CENTURY is not set
-CONFIG_RTC_DRV_DS1374=m
-CONFIG_RTC_DRV_DS1374_WDT=y
-CONFIG_RTC_DRV_DS1672=m
-# CONFIG_RTC_DRV_HYM8563 is not set
-CONFIG_RTC_DRV_MAX6900=m
-CONFIG_RTC_DRV_RS5C372=m
-CONFIG_RTC_DRV_ISL1208=m
-CONFIG_RTC_DRV_ISL12022=m
-# CONFIG_RTC_DRV_ISL12026 is not set
-CONFIG_RTC_DRV_X1205=m
-CONFIG_RTC_DRV_PCF8523=m
-CONFIG_RTC_DRV_PCF85063=m
-# CONFIG_RTC_DRV_PCF85363 is not set
-CONFIG_RTC_DRV_PCF8563=m
-CONFIG_RTC_DRV_PCF8583=m
-CONFIG_RTC_DRV_M41T80=m
-CONFIG_RTC_DRV_M41T80_WDT=y
-CONFIG_RTC_DRV_BQ32K=m
-# CONFIG_RTC_DRV_S35390A is not set
-CONFIG_RTC_DRV_FM3130=m
-CONFIG_RTC_DRV_RX8010=m
-CONFIG_RTC_DRV_RX8581=m
-CONFIG_RTC_DRV_RX8025=m
-CONFIG_RTC_DRV_EM3027=m
-CONFIG_RTC_DRV_RV8803=m
-
-#
-# SPI RTC drivers
-#
-CONFIG_RTC_DRV_M41T93=m
-CONFIG_RTC_DRV_M41T94=m
-# CONFIG_RTC_DRV_DS1302 is not set
-CONFIG_RTC_DRV_DS1305=m
-CONFIG_RTC_DRV_DS1343=m
-CONFIG_RTC_DRV_DS1347=m
-CONFIG_RTC_DRV_DS1390=m
-# CONFIG_RTC_DRV_MAX6916 is not set
-CONFIG_RTC_DRV_R9701=m
-CONFIG_RTC_DRV_RX4581=m
-# CONFIG_RTC_DRV_RX6110 is not set
-CONFIG_RTC_DRV_RS5C348=m
-CONFIG_RTC_DRV_MAX6902=m
-CONFIG_RTC_DRV_PCF2123=m
-CONFIG_RTC_DRV_MCP795=m
-CONFIG_RTC_I2C_AND_SPI=m
-
-#
-# SPI and I2C RTC drivers
-#
-CONFIG_RTC_DRV_DS3232=m
-CONFIG_RTC_DRV_DS3232_HWMON=y
-CONFIG_RTC_DRV_PCF2127=m
-CONFIG_RTC_DRV_RV3029C2=m
-# CONFIG_RTC_DRV_RV3029_HWMON is not set
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_DS1286=m
-CONFIG_RTC_DRV_DS1511=m
-CONFIG_RTC_DRV_DS1553=m
-CONFIG_RTC_DRV_DS1685_FAMILY=m
-CONFIG_RTC_DRV_DS1685=y
-# CONFIG_RTC_DRV_DS1689 is not set
-# CONFIG_RTC_DRV_DS17285 is not set
-# CONFIG_RTC_DRV_DS17485 is not set
-# CONFIG_RTC_DRV_DS17885 is not set
-# CONFIG_RTC_DS1685_PROC_REGS is not set
-CONFIG_RTC_DRV_DS1742=m
-CONFIG_RTC_DRV_DS2404=m
-CONFIG_RTC_DRV_EFI=y
-CONFIG_RTC_DRV_STK17TA8=m
-# CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_M48T35=m
-CONFIG_RTC_DRV_M48T59=m
-CONFIG_RTC_DRV_MSM6242=m
-CONFIG_RTC_DRV_BQ4802=m
-CONFIG_RTC_DRV_RP5C01=m
-CONFIG_RTC_DRV_V3020=m
-# CONFIG_RTC_DRV_ZYNQMP is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_RTC_DRV_PL030 is not set
-CONFIG_RTC_DRV_PL031=y
-# CONFIG_RTC_DRV_FTRTC010 is not set
-# CONFIG_RTC_DRV_SNVS is not set
-# CONFIG_RTC_DRV_XGENE is not set
-# CONFIG_RTC_DRV_R7301 is not set
-
-#
-# HID Sensor RTC drivers
-#
-# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
-CONFIG_DMADEVICES=y
-# CONFIG_DMADEVICES_DEBUG is not set
-
-#
-# DMA Devices
-#
-CONFIG_DMA_ENGINE=y
-CONFIG_DMA_ACPI=y
-CONFIG_DMA_OF=y
-# CONFIG_ALTERA_MSGDMA is not set
-# CONFIG_AMBA_PL08X is not set
-# CONFIG_BCM_SBA_RAID is not set
-# CONFIG_DW_AXI_DMAC is not set
-# CONFIG_FSL_EDMA is not set
-# CONFIG_INTEL_IDMA64 is not set
-# CONFIG_K3_DMA is not set
-# CONFIG_MV_XOR_V2 is not set
-# CONFIG_PL330_DMA is not set
-# CONFIG_XGENE_DMA is not set
-# CONFIG_XILINX_DMA is not set
-# CONFIG_XILINX_ZYNQMP_DMA is not set
-# CONFIG_QCOM_BAM_DMA is not set
-CONFIG_QCOM_HIDMA_MGMT=m
-CONFIG_QCOM_HIDMA=m
-CONFIG_DW_DMAC_CORE=m
-CONFIG_DW_DMAC=m
-CONFIG_DW_DMAC_PCI=m
-
-#
-# DMA Clients
-#
-CONFIG_ASYNC_TX_DMA=y
-# CONFIG_DMATEST is not set
-
-#
-# DMABUF options
-#
-CONFIG_SYNC_FILE=y
-# CONFIG_SW_SYNC is not set
-CONFIG_AUXDISPLAY=y
-# CONFIG_HD44780 is not set
-# CONFIG_IMG_ASCII_LCD is not set
-# CONFIG_HT16K33 is not set
-CONFIG_UIO=m
-CONFIG_UIO_CIF=m
-CONFIG_UIO_PDRV_GENIRQ=m
-# CONFIG_UIO_DMEM_GENIRQ is not set
-CONFIG_UIO_AEC=m
-CONFIG_UIO_SERCOS3=m
-CONFIG_UIO_PCI_GENERIC=m
-# CONFIG_UIO_NETX is not set
-# CONFIG_UIO_PRUSS is not set
-# CONFIG_UIO_MF624 is not set
-CONFIG_VFIO_IOMMU_TYPE1=m
-CONFIG_VFIO_VIRQFD=m
-CONFIG_VFIO=m
-CONFIG_VFIO_NOIOMMU=y
-CONFIG_VFIO_PCI=m
-CONFIG_VFIO_PCI_MMAP=y
-CONFIG_VFIO_PCI_INTX=y
-CONFIG_VFIO_PLATFORM=m
-# CONFIG_VFIO_AMBA is not set
-# CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET is not set
-# CONFIG_VFIO_PLATFORM_AMDXGBE_RESET is not set
-CONFIG_VFIO_MDEV=m
-CONFIG_VFIO_MDEV_DEVICE=m
-CONFIG_VFIO_SPIMDEV=m
-# CONFIG_VIRT_DRIVERS is not set
-CONFIG_VIRTIO=m
-CONFIG_VIRTIO_MENU=y
-CONFIG_VIRTIO_PCI=m
-CONFIG_VIRTIO_PCI_LEGACY=y
-CONFIG_VIRTIO_BALLOON=m
-CONFIG_VIRTIO_INPUT=m
-CONFIG_VIRTIO_MMIO=m
-# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
-
-#
-# Microsoft Hyper-V guest support
-#
-# CONFIG_STAGING is not set
-# CONFIG_GOLDFISH is not set
-CONFIG_CHROME_PLATFORMS=y
-# CONFIG_CHROMEOS_TBMC is not set
-# CONFIG_CROS_KBD_LED_BACKLIGHT is not set
-CONFIG_CLKDEV_LOOKUP=y
-CONFIG_HAVE_CLK_PREPARE=y
-CONFIG_COMMON_CLK=y
-
-#
-# Common Clock Framework
-#
-CONFIG_COMMON_CLK_VERSATILE=y
-CONFIG_CLK_SP810=y
-CONFIG_CLK_VEXPRESS_OSC=y
-# CONFIG_CLK_HSDK is not set
-# CONFIG_COMMON_CLK_MAX9485 is not set
-CONFIG_COMMON_CLK_SCPI=m
-# CONFIG_COMMON_CLK_SI5351 is not set
-# CONFIG_COMMON_CLK_SI514 is not set
-# CONFIG_COMMON_CLK_SI544 is not set
-# CONFIG_COMMON_CLK_SI570 is not set
-# CONFIG_COMMON_CLK_CDCE706 is not set
-# CONFIG_COMMON_CLK_CDCE925 is not set
-# CONFIG_COMMON_CLK_CS2000_CP is not set
-# CONFIG_CLK_QORIQ is not set
-CONFIG_COMMON_CLK_XGENE=y
-# CONFIG_COMMON_CLK_PWM is not set
-# CONFIG_COMMON_CLK_VC5 is not set
-CONFIG_COMMON_CLK_HI3516CV300=y
-CONFIG_COMMON_CLK_HI3519=y
-CONFIG_COMMON_CLK_HI3660=y
-CONFIG_COMMON_CLK_HI3798CV200=y
-# CONFIG_COMMON_CLK_HI6220 is not set
-CONFIG_RESET_HISI=y
-CONFIG_STUB_CLK_HI3660=y
-# CONFIG_COMMON_CLK_QCOM is not set
-CONFIG_HWSPINLOCK=y
-# CONFIG_HWSPINLOCK_QCOM is not set
-
-#
-# Clock Source drivers
-#
-CONFIG_TIMER_OF=y
-CONFIG_TIMER_ACPI=y
-CONFIG_TIMER_PROBE=y
-CONFIG_CLKSRC_MMIO=y
-CONFIG_ARM_ARCH_TIMER=y
-CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
-CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y
-CONFIG_FSL_ERRATUM_A008585=y
-CONFIG_HISILICON_ERRATUM_161010101=y
-CONFIG_ARM64_ERRATUM_858921=y
-CONFIG_ARM_TIMER_SP804=y
-CONFIG_MAILBOX=y
-CONFIG_ARM_MHU=m
-# CONFIG_PLATFORM_MHU is not set
-# CONFIG_PL320_MBOX is not set
-CONFIG_PCC=y
-# CONFIG_ALTERA_MBOX is not set
-CONFIG_HI3660_MBOX=y
-CONFIG_HI6220_MBOX=y
-# CONFIG_MAILBOX_TEST is not set
-# CONFIG_QCOM_APCS_IPC is not set
-CONFIG_XGENE_SLIMPRO_MBOX=m
-CONFIG_IOMMU_API=y
-CONFIG_IOMMU_SUPPORT=y
-
-#
-# Generic IOMMU Pagetable Support
-#
-CONFIG_IOMMU_IO_PGTABLE=y
-CONFIG_IOMMU_IO_PGTABLE_LPAE=y
-# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set
-# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
-# CONFIG_IOMMU_DEBUGFS is not set
-# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
-CONFIG_IOMMU_IOVA=y
-CONFIG_OF_IOMMU=y
-CONFIG_IOMMU_DMA=y
-CONFIG_ARM_SMMU=y
-CONFIG_ARM_SMMU_V3=y
-# CONFIG_QCOM_IOMMU is not set
-
-#
-# Remoteproc drivers
-#
-# CONFIG_REMOTEPROC is not set
-
-#
-# Rpmsg drivers
-#
-# CONFIG_RPMSG_QCOM_GLINK_RPM is not set
-# CONFIG_RPMSG_VIRTIO is not set
-# CONFIG_SOUNDWIRE is not set
-
-#
-# SOC (System On Chip) specific Drivers
-#
-
-#
-# Amlogic SoC drivers
-#
-
-#
-# Broadcom SoC drivers
-#
-# CONFIG_SOC_BRCMSTB is not set
-
-#
-# NXP/Freescale QorIQ SoC drivers
-#
-
-#
-# i.MX SoC drivers
-#
-
-#
-# Qualcomm SoC drivers
-#
-# CONFIG_QCOM_COMMAND_DB is not set
-# CONFIG_QCOM_GENI_SE is not set
-# CONFIG_QCOM_GSBI is not set
-# CONFIG_QCOM_LLCC is not set
-# CONFIG_QCOM_RMTFS_MEM is not set
-# CONFIG_QCOM_RPMH is not set
-# CONFIG_QCOM_SMEM is not set
-# CONFIG_SOC_TI is not set
-
-#
-# Xilinx SoC drivers
-#
-# CONFIG_XILINX_VCU is not set
-# CONFIG_PM_DEVFREQ is not set
-CONFIG_EXTCON=y
-
-#
-# Extcon Device Drivers
-#
-CONFIG_EXTCON_GPIO=m
-# CONFIG_EXTCON_MAX3355 is not set
-# CONFIG_EXTCON_QCOM_SPMI_MISC is not set
-# CONFIG_EXTCON_RT8973A is not set
-# CONFIG_EXTCON_SM5502 is not set
-# CONFIG_EXTCON_USB_GPIO is not set
-# CONFIG_MEMORY is not set
-# CONFIG_IIO is not set
-# CONFIG_NTB is not set
-# CONFIG_VME_BUS is not set
-CONFIG_PWM=y
-CONFIG_PWM_SYSFS=y
-# CONFIG_PWM_FSL_FTM is not set
-# CONFIG_PWM_HIBVT is not set
-# CONFIG_PWM_PCA9685 is not set
-
-#
-# IRQ chip support
-#
-CONFIG_IRQCHIP=y
-CONFIG_ARM_GIC=y
-CONFIG_ARM_GIC_MAX_NR=1
-CONFIG_ARM_GIC_V2M=y
-CONFIG_ARM_GIC_V3=y
-CONFIG_ARM_GIC_V3_ITS=y
-CONFIG_ARM_GIC_V3_ITS_PCI=y
-CONFIG_HISILICON_IRQ_MBIGEN=y
-CONFIG_PARTITION_PERCPU=y
-CONFIG_QCOM_IRQ_COMBINER=y
-# CONFIG_QCOM_PDC is not set
-# CONFIG_IPACK_BUS is not set
-CONFIG_RESET_CONTROLLER=y
-# CONFIG_RESET_QCOM_AOSS is not set
-# CONFIG_RESET_TI_SYSCON is not set
-CONFIG_COMMON_RESET_HI3660=y
-CONFIG_COMMON_RESET_HI6220=y
-CONFIG_FMC=m
-CONFIG_FMC_FAKEDEV=m
-CONFIG_FMC_TRIVIAL=m
-CONFIG_FMC_WRITE_EEPROM=m
-CONFIG_FMC_CHARDEV=m
-
-#
-# PHY Subsystem
-#
-CONFIG_GENERIC_PHY=y
-CONFIG_PHY_XGENE=y
-# CONFIG_BCM_KONA_USB2_PHY is not set
-CONFIG_PHY_HI6220_USB=m
-# CONFIG_PHY_HISTB_COMBPHY is not set
-# CONFIG_PHY_HISI_INNO_USB2 is not set
-# CONFIG_PHY_PXA_28NM_HSIC is not set
-# CONFIG_PHY_PXA_28NM_USB2 is not set
-# CONFIG_PHY_MAPPHONE_MDM6600 is not set
-# CONFIG_PHY_QCOM_APQ8064_SATA is not set
-# CONFIG_PHY_QCOM_IPQ806X_SATA is not set
-# CONFIG_PHY_QCOM_QMP is not set
-# CONFIG_PHY_QCOM_QUSB2 is not set
-# CONFIG_PHY_QCOM_UFS is not set
-# CONFIG_PHY_QCOM_USB_HS is not set
-# CONFIG_PHY_QCOM_USB_HSIC is not set
-# CONFIG_PHY_TUSB1210 is not set
-# CONFIG_POWERCAP is not set
-# CONFIG_MCB is not set
-
-#
-# Performance monitor support
-#
-# CONFIG_ARM_CCI_PMU is not set
-CONFIG_ARM_CCN=y
-CONFIG_ARM_PMU=y
-CONFIG_ARM_PMU_ACPI=y
-# CONFIG_ARM_SMMU_V3_PMU is not set
-# CONFIG_ARM_DSU_PMU is not set
-CONFIG_HISI_PMU=y
-CONFIG_QCOM_L2_PMU=y
-CONFIG_QCOM_L3_PMU=y
-CONFIG_XGENE_PMU=y
-CONFIG_ARM_SPE_PMU=y
-CONFIG_RAS=y
-
-#
-# Android
-#
-# CONFIG_ANDROID is not set
-CONFIG_LIBNVDIMM=m
-CONFIG_BLK_DEV_PMEM=m
-CONFIG_ND_BLK=m
-CONFIG_ND_CLAIM=y
-CONFIG_ND_BTT=m
-CONFIG_BTT=y
-CONFIG_OF_PMEM=m
-CONFIG_DAX_DRIVER=y
-CONFIG_DAX=y
-CONFIG_DEV_DAX=m
-CONFIG_NVMEM=y
-# CONFIG_QCOM_QFPROM is not set
-
-#
-# HW tracing support
-#
-# CONFIG_STM is not set
-# CONFIG_INTEL_TH is not set
-# CONFIG_FPGA is not set
-# CONFIG_FSI is not set
-CONFIG_TEE=m
-
-#
-# TEE drivers
-#
-# CONFIG_OPTEE is not set
-# CONFIG_SIOX is not set
-# CONFIG_SLIMBUS is not set
-
-#
-# File systems
-#
-CONFIG_DCACHE_WORD_ACCESS=y
-CONFIG_FS_IOMAP=y
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-CONFIG_EXT4_FS=m
-CONFIG_EXT4_USE_FOR_EXT2=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-# CONFIG_EXT4_ENCRYPTION is not set
-# CONFIG_EXT4_DEBUG is not set
-CONFIG_JBD2=m
-# CONFIG_JBD2_DEBUG is not set
-CONFIG_FS_MBCACHE=m
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_XFS_FS=m
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_ONLINE_SCRUB is not set
-# CONFIG_XFS_WARN is not set
-# CONFIG_XFS_DEBUG is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
-# CONFIG_NILFS2_FS is not set
-# CONFIG_F2FS_FS is not set
-CONFIG_FS_DAX=y
-CONFIG_FS_POSIX_ACL=y
-CONFIG_EXPORTFS=y
-CONFIG_EXPORTFS_BLOCK_OPS=y
-CONFIG_FILE_LOCKING=y
-CONFIG_MANDATORY_FILE_LOCKING=y
-# CONFIG_FS_ENCRYPTION is not set
-CONFIG_FSNOTIFY=y
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY_USER=y
-CONFIG_FANOTIFY=y
-CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-CONFIG_PRINT_QUOTA_WARNING=y
-# CONFIG_QUOTA_DEBUG is not set
-CONFIG_QUOTA_TREE=y
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-CONFIG_QUOTACTL=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_AUTOFS_FS=y
-CONFIG_FUSE_FS=m
-CONFIG_CUSE=m
-CONFIG_OVERLAY_FS=m
-# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set
-CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y
-# CONFIG_OVERLAY_FS_INDEX is not set
-# CONFIG_OVERLAY_FS_XINO_AUTO is not set
-# CONFIG_OVERLAY_FS_METACOPY is not set
-
-#
-# Caches
-#
-CONFIG_FSCACHE=m
-CONFIG_FSCACHE_STATS=y
-# CONFIG_FSCACHE_HISTOGRAM is not set
-# CONFIG_FSCACHE_DEBUG is not set
-# CONFIG_FSCACHE_OBJECT_LIST is not set
-CONFIG_CACHEFILES=m
-# CONFIG_CACHEFILES_DEBUG is not set
-# CONFIG_CACHEFILES_HISTOGRAM is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-# CONFIG_FAT_DEFAULT_UTF8 is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_VMCORE=y
-# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set
-CONFIG_PROC_SYSCTL=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_PROC_CHILDREN=y
-CONFIG_KERNFS=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_MEMFD_CREATE=y
-CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
-CONFIG_CONFIGFS_FS=y
-CONFIG_EFIVAR_FS=y
-CONFIG_MISC_FILESYSTEMS=y
-# CONFIG_ORANGEFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_UBIFS_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_CRAMFS_BLOCKDEV=y
-# CONFIG_CRAMFS_MTD is not set
-CONFIG_SQUASHFS=m
-CONFIG_SQUASHFS_FILE_CACHE=y
-# CONFIG_SQUASHFS_FILE_DIRECT is not set
-CONFIG_SQUASHFS_DECOMP_SINGLE=y
-# CONFIG_SQUASHFS_DECOMP_MULTI is not set
-# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set
-CONFIG_SQUASHFS_XATTR=y
-CONFIG_SQUASHFS_ZLIB=y
-CONFIG_SQUASHFS_LZ4=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_SQUASHFS_XZ=y
-# CONFIG_SQUASHFS_ZSTD is not set
-# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
-# CONFIG_SQUASHFS_EMBEDDED is not set
-CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX6FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_PSTORE=y
-CONFIG_PSTORE_DEFLATE_COMPRESS=y
-# CONFIG_PSTORE_LZO_COMPRESS is not set
-# CONFIG_PSTORE_LZ4_COMPRESS is not set
-# CONFIG_PSTORE_LZ4HC_COMPRESS is not set
-# CONFIG_PSTORE_842_COMPRESS is not set
-# CONFIG_PSTORE_ZSTD_COMPRESS is not set
-CONFIG_PSTORE_COMPRESS=y
-CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y
-CONFIG_PSTORE_COMPRESS_DEFAULT="deflate"
-# CONFIG_PSTORE_CONSOLE is not set
-# CONFIG_PSTORE_PMSG is not set
-# CONFIG_PSTORE_FTRACE is not set
-CONFIG_PSTORE_RAM=m
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V2=m
-CONFIG_NFS_V3=m
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=m
-# CONFIG_NFS_SWAP is not set
-CONFIG_NFS_V4_1=y
-CONFIG_NFS_V4_2=y
-CONFIG_PNFS_FILE_LAYOUT=m
-CONFIG_PNFS_BLOCK=m
-CONFIG_PNFS_FLEXFILE_LAYOUT=m
-CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
-# CONFIG_NFS_V4_1_MIGRATION is not set
-CONFIG_NFS_V4_SECURITY_LABEL=y
-CONFIG_NFS_FSCACHE=y
-# CONFIG_NFS_USE_LEGACY_DNS is not set
-CONFIG_NFS_USE_KERNEL_DNS=y
-CONFIG_NFS_DEBUG=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-# CONFIG_NFSD_BLOCKLAYOUT is not set
-# CONFIG_NFSD_SCSILAYOUT is not set
-# CONFIG_NFSD_FLEXFILELAYOUT is not set
-CONFIG_NFSD_V4_SECURITY_LABEL=y
-# CONFIG_NFSD_FAULT_INJECTION is not set
-CONFIG_GRACE_PERIOD=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_ACL_SUPPORT=m
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-CONFIG_SUNRPC_GSS=m
-CONFIG_SUNRPC_BACKCHANNEL=y
-CONFIG_RPCSEC_GSS_KRB5=m
-CONFIG_SUNRPC_DEBUG=y
-CONFIG_SUNRPC_XPRT_RDMA=m
-CONFIG_CEPH_FS=m
-# CONFIG_CEPH_FSCACHE is not set
-CONFIG_CEPH_FS_POSIX_ACL=y
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS2 is not set
-CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
-CONFIG_CIFS_WEAK_PW_HASH=y
-CONFIG_CIFS_UPCALL=y
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_CIFS_ACL=y
-CONFIG_CIFS_DEBUG=y
-# CONFIG_CIFS_DEBUG2 is not set
-# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set
-CONFIG_CIFS_DFS_UPCALL=y
-# CONFIG_CIFS_SMB_DIRECT is not set
-# CONFIG_CIFS_FSCACHE is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_MAC_ROMAN=m
-CONFIG_NLS_MAC_CELTIC=m
-CONFIG_NLS_MAC_CENTEURO=m
-CONFIG_NLS_MAC_CROATIAN=m
-CONFIG_NLS_MAC_CYRILLIC=m
-CONFIG_NLS_MAC_GAELIC=m
-CONFIG_NLS_MAC_GREEK=m
-CONFIG_NLS_MAC_ICELAND=m
-CONFIG_NLS_MAC_INUIT=m
-CONFIG_NLS_MAC_ROMANIAN=m
-CONFIG_NLS_MAC_TURKISH=m
-CONFIG_NLS_UTF8=m
-# CONFIG_DLM is not set
-CONFIG_RESCTRL=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_COMPAT=y
-CONFIG_PERSISTENT_KEYRINGS=y
-CONFIG_BIG_KEYS=y
-CONFIG_TRUSTED_KEYS=m
-CONFIG_ENCRYPTED_KEYS=m
-# CONFIG_KEY_DH_OPERATIONS is not set
-# CONFIG_SECURITY_DMESG_RESTRICT is not set
-CONFIG_SECURITY=y
-CONFIG_SECURITY_WRITABLE_HOOKS=y
-CONFIG_SECURITYFS=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_SECURITY_INFINIBAND=y
-CONFIG_SECURITY_NETWORK_XFRM=y
-# CONFIG_SECURITY_PATH is not set
-CONFIG_LSM_MMAP_MIN_ADDR=65535
-CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
-CONFIG_HARDENED_USERCOPY=y
-CONFIG_HARDENED_USERCOPY_FALLBACK=y
-# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set
-CONFIG_FORTIFY_SOURCE=y
-# CONFIG_STATIC_USERMODEHELPER is not set
-CONFIG_SECURITY_SELINUX=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
-CONFIG_SECURITY_SELINUX_DISABLE=y
-CONFIG_SECURITY_SELINUX_DEVELOP=y
-CONFIG_SECURITY_SELINUX_AVC_STATS=y
-CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
-# CONFIG_SECURITY_SMACK is not set
-# CONFIG_SECURITY_TOMOYO is not set
-# CONFIG_SECURITY_APPARMOR is not set
-# CONFIG_SECURITY_LOADPIN is not set
-CONFIG_SECURITY_YAMA=y
-# CONFIG_INTEGRITY is not set
-CONFIG_DEFAULT_SECURITY_SELINUX=y
-# CONFIG_DEFAULT_SECURITY_DAC is not set
-CONFIG_DEFAULT_SECURITY="selinux"
-CONFIG_XOR_BLOCKS=m
-CONFIG_ASYNC_CORE=m
-CONFIG_ASYNC_MEMCPY=m
-CONFIG_ASYNC_XOR=m
-CONFIG_ASYNC_PQ=m
-CONFIG_ASYNC_RAID6_RECOV=m
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-CONFIG_CRYPTO_FIPS=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_RNG_DEFAULT=y
-CONFIG_CRYPTO_AKCIPHER2=y
-CONFIG_CRYPTO_AKCIPHER=y
-CONFIG_CRYPTO_KPP2=y
-CONFIG_CRYPTO_ACOMP2=y
-CONFIG_CRYPTO_RSA=y
-# CONFIG_CRYPTO_DH is not set
-# CONFIG_CRYPTO_ECDH is not set
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-CONFIG_CRYPTO_USER=m
-# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_NULL2=y
-CONFIG_CRYPTO_PCRYPT=m
-CONFIG_CRYPTO_WORKQUEUE=y
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_SIMD=m
-CONFIG_CRYPTO_ENGINE=m
-
-#
-# Authenticated Encryption with Associated Data
-#
-CONFIG_CRYPTO_CCM=m
-CONFIG_CRYPTO_GCM=y
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-# CONFIG_CRYPTO_AEGIS128 is not set
-# CONFIG_CRYPTO_AEGIS128L is not set
-# CONFIG_CRYPTO_AEGIS256 is not set
-# CONFIG_CRYPTO_MORUS640 is not set
-# CONFIG_CRYPTO_MORUS1280 is not set
-CONFIG_CRYPTO_SEQIV=y
-CONFIG_CRYPTO_ECHAINIV=m
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CFB is not set
-CONFIG_CRYPTO_CTR=y
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-# CONFIG_CRYPTO_KEYWRAP is not set
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_CMAC=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_CRCT10DIF=y
-CONFIG_CRYPTO_GHASH=y
-CONFIG_CRYPTO_POLY1305=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_SHA3=m
-# CONFIG_CRYPTO_SM3 is not set
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-
-#
-# Ciphers
-#
-CONFIG_CRYPTO_AES=y
-# CONFIG_CRYPTO_AES_TI is not set
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_BLOWFISH_COMMON=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST_COMMON=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
-CONFIG_CRYPTO_CHACHA20=m
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_SM4=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-
-#
-# Compression
-#
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_LZO=y
-# CONFIG_CRYPTO_842 is not set
-CONFIG_CRYPTO_LZ4=m
-CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ZSTD is not set
-
-#
-# Random Number Generation
-#
-CONFIG_CRYPTO_ANSI_CPRNG=m
-CONFIG_CRYPTO_DRBG_MENU=y
-CONFIG_CRYPTO_DRBG_HMAC=y
-CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
-CONFIG_CRYPTO_DRBG=y
-CONFIG_CRYPTO_JITTERENTROPY=y
-CONFIG_CRYPTO_USER_API=y
-CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_USER_API_SKCIPHER=y
-CONFIG_CRYPTO_USER_API_RNG=y
-CONFIG_CRYPTO_USER_API_AEAD=y
-CONFIG_CRYPTO_HASH_INFO=y
-CONFIG_CRYPTO_HW=y
-CONFIG_CRYPTO_DEV_CCP=y
-CONFIG_CRYPTO_DEV_CCP_DD=m
-CONFIG_CRYPTO_DEV_SP_CCP=y
-CONFIG_CRYPTO_DEV_CCP_CRYPTO=m
-CONFIG_CRYPTO_DEV_CPT=m
-CONFIG_CAVIUM_CPT=m
-# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set
-CONFIG_CRYPTO_DEV_CAVIUM_ZIP=m
-# CONFIG_CRYPTO_DEV_QCE is not set
-# CONFIG_CRYPTO_DEV_QCOM_RNG is not set
-CONFIG_CRYPTO_DEV_CHELSIO=m
-CONFIG_CHELSIO_IPSEC_INLINE=y
-# CONFIG_CRYPTO_DEV_CHELSIO_TLS is not set
-CONFIG_CRYPTO_DEV_VIRTIO=m
-# CONFIG_CRYPTO_DEV_CCREE is not set
-# CONFIG_CRYPTO_DEV_HISI_SEC is not set
-# CONFIG_CRYPTO_DEV_HISILICON is not set
-CONFIG_ASYMMETRIC_KEY_TYPE=y
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
-CONFIG_X509_CERTIFICATE_PARSER=y
-CONFIG_PKCS7_MESSAGE_PARSER=y
-# CONFIG_PKCS7_TEST_KEY is not set
-CONFIG_SIGNED_PE_FILE_VERIFICATION=y
-# CONFIG_PGP_LIBRARY is not set
-# CONFIG_PGP_KEY_PARSER is not set
-# CONFIG_PGP_PRELOAD is not set
-
-#
-# Certificates for signature checking
-#
-CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
-CONFIG_SYSTEM_TRUSTED_KEYRING=y
-CONFIG_SYSTEM_TRUSTED_KEYS=""
-# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
-# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
-# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
-# CONFIG_PGP_PRELOAD_PUBLIC_KEYS is not set
-CONFIG_BINARY_PRINTF=y
-
-#
-# Library routines
-#
-CONFIG_RAID6_PQ=m
-CONFIG_BITREVERSE=y
-CONFIG_HAVE_ARCH_BITREVERSE=y
-CONFIG_RATIONAL=y
-CONFIG_GENERIC_STRNCPY_FROM_USER=y
-CONFIG_GENERIC_STRNLEN_USER=y
-CONFIG_GENERIC_NET_UTILS=y
-CONFIG_GENERIC_PCI_IOMAP=y
-CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
-CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
-CONFIG_INDIRECT_PIO=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC32_SELFTEST is not set
-CONFIG_CRC32_SLICEBY8=y
-# CONFIG_CRC32_SLICEBY4 is not set
-# CONFIG_CRC32_SARWATE is not set
-# CONFIG_CRC32_BIT is not set
-# CONFIG_CRC64 is not set
-# CONFIG_CRC4 is not set
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
-CONFIG_CRC8=m
-CONFIG_AUDIT_GENERIC=y
-CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
-CONFIG_AUDIT_COMPAT_GENERIC=y
-# CONFIG_RANDOM32_SELFTEST is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=y
-CONFIG_LZO_DECOMPRESS=y
-CONFIG_LZ4_COMPRESS=m
-CONFIG_LZ4HC_COMPRESS=m
-CONFIG_LZ4_DECOMPRESS=y
-CONFIG_XZ_DEC=y
-CONFIG_XZ_DEC_X86=y
-CONFIG_XZ_DEC_POWERPC=y
-CONFIG_XZ_DEC_IA64=y
-CONFIG_XZ_DEC_ARM=y
-CONFIG_XZ_DEC_ARMTHUMB=y
-CONFIG_XZ_DEC_SPARC=y
-CONFIG_XZ_DEC_BCJ=y
-# CONFIG_XZ_DEC_TEST is not set
-CONFIG_DECOMPRESS_GZIP=y
-CONFIG_DECOMPRESS_BZIP2=y
-CONFIG_DECOMPRESS_LZMA=y
-CONFIG_DECOMPRESS_XZ=y
-CONFIG_DECOMPRESS_LZO=y
-CONFIG_DECOMPRESS_LZ4=y
-CONFIG_GENERIC_ALLOCATOR=y
-CONFIG_REED_SOLOMON=m
-CONFIG_REED_SOLOMON_ENC8=y
-CONFIG_REED_SOLOMON_DEC8=y
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
-CONFIG_BTREE=y
-CONFIG_INTERVAL_TREE=y
-CONFIG_RADIX_TREE_MULTIORDER=y
-CONFIG_ASSOCIATIVE_ARRAY=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT_MAP=y
-CONFIG_HAS_DMA=y
-CONFIG_NEED_SG_DMA_LENGTH=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_DMA_DIRECT_OPS=y
-CONFIG_DMA_VIRT_OPS=y
-CONFIG_SWIOTLB=y
-CONFIG_SGL_ALLOC=y
-CONFIG_CHECK_SIGNATURE=y
-CONFIG_CPU_RMAP=y
-CONFIG_DQL=y
-CONFIG_GLOB=y
-# CONFIG_GLOB_SELFTEST is not set
-CONFIG_NLATTR=y
-CONFIG_CLZ_TAB=y
-CONFIG_CORDIC=m
-# CONFIG_DDR is not set
-CONFIG_IRQ_POLL=y
-CONFIG_MPILIB=y
-CONFIG_LIBFDT=y
-CONFIG_OID_REGISTRY=y
-CONFIG_UCS2_STRING=y
-CONFIG_FONT_SUPPORT=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_SG_POOL=y
-CONFIG_ARCH_HAS_SG_CHAIN=y
-CONFIG_ARCH_HAS_PMEM_API=y
-CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
-CONFIG_SBITMAP=y
-# CONFIG_STRING_SELFTEST is not set
-
-#
-# Kernel hacking
-#
-
-#
-# printk and dmesg options
-#
-CONFIG_PRINTK_TIME=y
-CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
-CONFIG_CONSOLE_LOGLEVEL_QUIET=4
-CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
-CONFIG_BOOT_PRINTK_DELAY=y
-CONFIG_DYNAMIC_DEBUG=y
-
-#
-# Compile-time checks and compiler options
-#
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_INFO_REDUCED is not set
-# CONFIG_DEBUG_INFO_SPLIT is not set
-CONFIG_DEBUG_INFO_DWARF4=y
-# CONFIG_GDB_SCRIPTS is not set
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=2048
-CONFIG_STRIP_ASM_SYMS=y
-# CONFIG_READABLE_ASM is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_PAGE_OWNER is not set
-CONFIG_DEBUG_FS=y
-CONFIG_HEADERS_CHECK=y
-CONFIG_DEBUG_SECTION_MISMATCH=y
-CONFIG_SECTION_MISMATCH_WARN_ONLY=y
-CONFIG_ARCH_WANT_FRAME_POINTERS=y
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
-CONFIG_MAGIC_SYSRQ_SERIAL=y
-CONFIG_DEBUG_KERNEL=y
-
-#
-# Memory Debugging
-#
-# CONFIG_PAGE_EXTENSION is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_PAGE_POISONING is not set
-# CONFIG_DEBUG_PAGE_REF is not set
-# CONFIG_DEBUG_RODATA_TEST is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-# CONFIG_DEBUG_KMEMLEAK is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_VM is not set
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-# CONFIG_DEBUG_VIRTUAL is not set
-CONFIG_DEBUG_MEMORY_INIT=y
-# CONFIG_DEBUG_PER_CPU_MAPS is not set
-CONFIG_HAVE_ARCH_KASAN=y
-# CONFIG_KASAN is not set
-CONFIG_ARCH_HAS_KCOV=y
-CONFIG_CC_HAS_SANCOV_TRACE_PC=y
-# CONFIG_KCOV is not set
-CONFIG_DEBUG_SHIRQ=y
-
-#
-# Debug Lockups and Hangs
-#
-CONFIG_LOCKUP_DETECTOR=y
-CONFIG_SOFTLOCKUP_DETECTOR=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_HARDLOCKUP_DETECTOR_PERF=y
-CONFIG_HARDLOCKUP_DETECTOR=y
-CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
-CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
-# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
-CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
-# CONFIG_WQ_WATCHDOG is not set
-CONFIG_PANIC_ON_OOPS=y
-CONFIG_PANIC_ON_OOPS_VALUE=1
-CONFIG_PANIC_TIMEOUT=0
-CONFIG_SCHED_DEBUG=y
-CONFIG_SCHED_INFO=y
-CONFIG_SCHEDSTATS=y
-# CONFIG_SCHED_STACK_END_CHECK is not set
-# CONFIG_DEBUG_TIMEKEEPING is not set
-
-#
-# Lock Debugging (spinlocks, mutexes, etc...)
-#
-CONFIG_LOCK_DEBUGGING_SUPPORT=y
-# CONFIG_PROVE_LOCKING is not set
-# CONFIG_LOCK_STAT is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
-# CONFIG_DEBUG_RWSEMS is not set
-# CONFIG_DEBUG_LOCK_ALLOC is not set
-# CONFIG_DEBUG_ATOMIC_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_LOCK_TORTURE_TEST is not set
-# CONFIG_WW_MUTEX_SELFTEST is not set
-CONFIG_STACKTRACE=y
-# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_HAVE_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_LIST=y
-# CONFIG_DEBUG_PI_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_DEBUG_CREDENTIALS is not set
-
-#
-# RCU Debugging
-#
-# CONFIG_RCU_PERF_TEST is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-CONFIG_RCU_CPU_STALL_TIMEOUT=60
-# CONFIG_RCU_TRACE is not set
-# CONFIG_RCU_EQS_DEBUG is not set
-# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
-# CONFIG_NOTIFIER_ERROR_INJECTION is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_TRACER_MAX_TRACE=y
-CONFIG_TRACE_CLOCK=y
-CONFIG_RING_BUFFER=y
-CONFIG_EVENT_TRACING=y
-CONFIG_CONTEXT_SWITCH_TRACER=y
-CONFIG_TRACING=y
-CONFIG_GENERIC_TRACER=y
-CONFIG_TRACING_SUPPORT=y
-CONFIG_FTRACE=y
-CONFIG_FUNCTION_TRACER=y
-CONFIG_FUNCTION_GRAPH_TRACER=y
-# CONFIG_PREEMPTIRQ_EVENTS is not set
-# CONFIG_IRQSOFF_TRACER is not set
-CONFIG_SCHED_TRACER=y
-CONFIG_HWLAT_TRACER=y
-CONFIG_FTRACE_SYSCALLS=y
-CONFIG_TRACER_SNAPSHOT=y
-# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set
-CONFIG_BRANCH_PROFILE_NONE=y
-# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
-CONFIG_STACK_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_KPROBE_EVENTS=y
-CONFIG_UPROBE_EVENTS=y
-CONFIG_BPF_EVENTS=y
-CONFIG_PROBE_EVENTS=y
-CONFIG_DYNAMIC_FTRACE=y
-# CONFIG_FUNCTION_PROFILER is not set
-CONFIG_FTRACE_MCOUNT_RECORD=y
-# CONFIG_FTRACE_STARTUP_TEST is not set
-CONFIG_TRACING_MAP=y
-CONFIG_HIST_TRIGGERS=y
-# CONFIG_TRACEPOINT_BENCHMARK is not set
-CONFIG_RING_BUFFER_BENCHMARK=m
-# CONFIG_RING_BUFFER_STARTUP_TEST is not set
-# CONFIG_PREEMPTIRQ_DELAY_TEST is not set
-# CONFIG_TRACE_EVAL_MAP_FILE is not set
-# CONFIG_TRACING_EVENTS_GPIO is not set
-# CONFIG_DMA_API_DEBUG is not set
-CONFIG_RUNTIME_TESTING_MENU=y
-# CONFIG_LKDTM is not set
-# CONFIG_TEST_LIST_SORT is not set
-# CONFIG_TEST_SORT is not set
-# CONFIG_KPROBES_SANITY_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_RBTREE_TEST is not set
-# CONFIG_INTERVAL_TREE_TEST is not set
-# CONFIG_PERCPU_TEST is not set
-CONFIG_ATOMIC64_SELFTEST=y
-CONFIG_ASYNC_RAID6_TEST=m
-# CONFIG_TEST_HEXDUMP is not set
-# CONFIG_TEST_STRING_HELPERS is not set
-CONFIG_TEST_KSTRTOX=y
-# CONFIG_TEST_PRINTF is not set
-# CONFIG_TEST_BITMAP is not set
-# CONFIG_TEST_BITFIELD is not set
-# CONFIG_TEST_UUID is not set
-# CONFIG_TEST_OVERFLOW is not set
-# CONFIG_TEST_RHASHTABLE is not set
-# CONFIG_TEST_HASH is not set
-# CONFIG_TEST_IDA is not set
-# CONFIG_TEST_LKM is not set
-# CONFIG_TEST_USER_COPY is not set
-# CONFIG_TEST_BPF is not set
-# CONFIG_FIND_BIT_BENCHMARK is not set
-# CONFIG_TEST_FIRMWARE is not set
-# CONFIG_TEST_SYSCTL is not set
-# CONFIG_TEST_UDELAY is not set
-# CONFIG_TEST_STATIC_KEYS is not set
-# CONFIG_TEST_KMOD is not set
-# CONFIG_TEST_FREE_PAGES is not set
-# CONFIG_MEMTEST is not set
-# CONFIG_BUG_ON_DATA_CORRUPTION is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_KGDB=y
-CONFIG_KGDB_SERIAL_CONSOLE=y
-CONFIG_KGDB_TESTS=y
-# CONFIG_KGDB_TESTS_ON_BOOT is not set
-CONFIG_KGDB_KDB=y
-CONFIG_KDB_DEFAULT_ENABLE=0x0
-CONFIG_KDB_KEYBOARD=y
-CONFIG_KDB_CONTINUE_CATASTROPHIC=0
-CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
-# CONFIG_UBSAN is not set
-CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
-CONFIG_STRICT_DEVMEM=y
-CONFIG_IO_STRICT_DEVMEM=y
-# CONFIG_ARM64_PTDUMP_DEBUGFS is not set
-# CONFIG_PID_IN_CONTEXTIDR is not set
-# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set
-# CONFIG_DEBUG_WX is not set
-# CONFIG_DEBUG_ALIGN_RODATA is not set
-# CONFIG_DEBUG_EFI is not set
-# CONFIG_ARM64_RELOC_TEST is not set
-# CONFIG_CORESIGHT is not set
--
2.25.1
1
17
[PATCH OLK-5.10 00/20] arm: reduce p2v alignment requirement to 2 MiB and adrl replacement
by Zhao Hongjiang 23 Jan '21
by Zhao Hongjiang 23 Jan '21
23 Jan '21
http://openeuler.huawei.com/bugzilla/show_bug.cgi?id=46882
Ard Biesheuvel (20):
ARM: p2v: fix handling of LPAE translation in BE mode
ARM: assembler: introduce adr_l, ldr_l and str_l macros
ARM: module: add support for place relative relocations
ARM: p2v: move patching code to separate assembler source file
ARM: p2v: factor out shared loop processing
ARM: p2v: factor out BE8 handling
ARM: p2v: drop redundant 'type' argument from __pv_stub
ARM: p2v: use relative references in patch site arrays
ARM: p2v: simplify __fixup_pv_table()
ARM: p2v: switch to MOVW for Thumb2 and ARM/LPAE
ARM: p2v: reduce p2v alignment requirement to 2 MiB
ARM: efistub: replace adrl pseudo-op with adr_l macro invocation
ARM: head-common.S: use PC-relative insn sequence for __proc_info
ARM: head-common.S: use PC-relative insn sequence for idmap creation
ARM: head.S: use PC-relative insn sequence for secondary_data
ARM: kernel: use relative references for UP/SMP alternatives
ARM: head: use PC-relative insn sequence for __smp_alt
ARM: sleep.S: use PC-relative insn sequence for
sleep_save_sp/mpidr_hash
ARM: head.S: use PC relative insn sequence to calculate PHYS_OFFSET
ARM: kvm: replace open coded VA->PA calculations with adr_l call
arch/arm/Kconfig | 2 +-
arch/arm/boot/compressed/head.S | 18 +--
arch/arm/include/asm/assembler.h | 88 +++++++++++-
arch/arm/include/asm/elf.h | 5 +
arch/arm/include/asm/memory.h | 57 +++++---
arch/arm/include/asm/processor.h | 2 +-
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/head-common.S | 22 +--
arch/arm/kernel/head.S | 205 ++------------------------
arch/arm/kernel/hyp-stub.S | 27 ++--
arch/arm/kernel/module.c | 20 ++-
arch/arm/kernel/phys2virt.S | 238 +++++++++++++++++++++++++++++++
arch/arm/kernel/sleep.S | 19 +--
13 files changed, 431 insertions(+), 273 deletions(-)
create mode 100644 arch/arm/kernel/phys2virt.S
--
2.25.1
2
21
[PATCH OLK-5.10 v2 0/2] config: add initial openeuler_defconfig for arm64 & x86
by Xie XiuQi 18 Jan '21
by Xie XiuQi 18 Jan '21
18 Jan '21
Add initial configs for arm64 & x86 platform.
Use openEuler-20.03's config as base, re-generate it on 5.10 kernel.
The major changes:
- use 52 bit VA & PA
- enable CONFIG_PSI
- support more kunpeng drivers on arm64
Xie XiuQi (2):
config: add initial openeuler_defconfig for arm64
config: add initial openeuler_defconfig for x86
arch/arm64/configs/openeuler_defconfig | 7069 ++++++++++++++++++++
arch/x86/configs/openeuler_defconfig | 8273 ++++++++++++++++++++++++
2 files changed, 15342 insertions(+)
create mode 100644 arch/arm64/configs/openeuler_defconfig
create mode 100644 arch/x86/configs/openeuler_defconfig
--
2.20.1
1
2
18 Jan '21
From: Yang Shi <yang.shi(a)linux.alibaba.com>
mainline inclusion
from mainline-v5.4-rc1
commit 364c1eebe453f06f0c1e837eb155a5725c9cd272
category: bugfix
bugzilla: 47240
CVE: NA
-------------------------------------------------
Patch series "Make deferred split shrinker memcg aware", v6.
Currently THP deferred split shrinker is not memcg aware, this may cause
premature OOM with some configuration. For example the below test would
run into premature OOM easily:
$ cgcreate -g memory:thp
$ echo 4G > /sys/fs/cgroup/memory/thp/memory/limit_in_bytes
$ cgexec -g memory:thp transhuge-stress 4000
transhuge-stress comes from kernel selftest.
It is easy to hit OOM, but there are still a lot THP on the deferred split
queue, memcg direct reclaim can't touch them since the deferred split
shrinker is not memcg aware.
Convert deferred split shrinker memcg aware by introducing per memcg
deferred split queue. The THP should be on either per node or per memcg
deferred split queue if it belongs to a memcg. When the page is
immigrated to the other memcg, it will be immigrated to the target memcg's
deferred split queue too.
Reuse the second tail page's deferred_list for per memcg list since the
same THP can't be on multiple deferred split queues.
Make deferred split shrinker not depend on memcg kmem since it is not
slab. It doesn't make sense to not shrink THP even though memcg kmem is
disabled.
With the above change the test demonstrated above doesn't trigger OOM even
though with cgroup.memory=nokmem.
This patch (of 4):
Put split_queue, split_queue_lock and split_queue_len into a struct in
order to reduce code duplication when we convert deferred_split to memcg
aware in the later patches.
Link: http://lkml.kernel.org/r/1565144277-36240-2-git-send-email-yang.shi@linux.a…
Signed-off-by: Yang Shi <yang.shi(a)linux.alibaba.com>
Suggested-by: "Kirill A . Shutemov" <kirill.shutemov(a)linux.intel.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov(a)linux.intel.com>
Reviewed-by: Kirill Tkhai <ktkhai(a)virtuozzo.com>
Cc: Johannes Weiner <hannes(a)cmpxchg.org>
Cc: Michal Hocko <mhocko(a)suse.com>
Cc: Hugh Dickins <hughd(a)google.com>
Cc: Shakeel Butt <shakeelb(a)google.com>
Cc: David Rientjes <rientjes(a)google.com>
Cc: Qian Cai <cai(a)lca.pw>
Cc: Vladimir Davydov <vdavydov.dev(a)gmail.com>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
Signed-off-by: Liu Shixin <liushixin2(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/mmzone.h | 12 ++++++++---
mm/huge_memory.c | 45 +++++++++++++++++++++++-------------------
mm/page_alloc.c | 8 +++++---
3 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 1d7c5dd03ed89..3bd2f5e2a344f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -612,6 +612,14 @@ struct zonelist {
extern struct page *mem_map;
#endif
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+struct deferred_split {
+ spinlock_t split_queue_lock;
+ struct list_head split_queue;
+ unsigned long split_queue_len;
+};
+#endif
+
/*
* On NUMA machines, each NUMA node would have a pg_data_t to describe
* it's memory layout. On UMA machines there is a single pglist_data which
@@ -698,9 +706,7 @@ typedef struct pglist_data {
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- spinlock_t split_queue_lock;
- struct list_head split_queue;
- unsigned long split_queue_len;
+ struct deferred_split deferred_split_queue;
#endif
/* Fields commonly accessed by the page reclaim scanner */
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index c2013b3e92e74..936092f8d4b16 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2697,6 +2697,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
{
struct page *head = compound_head(page);
struct pglist_data *pgdata = NODE_DATA(page_to_nid(head));
+ struct deferred_split *ds_queue = &pgdata->deferred_split_queue;
struct anon_vma *anon_vma = NULL;
struct address_space *mapping = NULL;
int count, mapcount, extra_pins, ret;
@@ -2786,17 +2787,17 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
}
/* Prevent deferred_split_scan() touching ->_refcount */
- spin_lock(&pgdata->split_queue_lock);
+ spin_lock(&ds_queue->split_queue_lock);
count = page_count(head);
mapcount = total_mapcount(head);
if (!mapcount && page_ref_freeze(head, 1 + extra_pins)) {
if (!list_empty(page_deferred_list(head))) {
- pgdata->split_queue_len--;
+ ds_queue->split_queue_len--;
list_del(page_deferred_list(head));
}
if (mapping)
__dec_node_page_state(page, NR_SHMEM_THPS);
- spin_unlock(&pgdata->split_queue_lock);
+ spin_unlock(&ds_queue->split_queue_lock);
__split_huge_page(page, list, end, flags);
ret = 0;
} else {
@@ -2808,7 +2809,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
dump_page(page, "total_mapcount(head) > 0");
BUG();
}
- spin_unlock(&pgdata->split_queue_lock);
+ spin_unlock(&ds_queue->split_queue_lock);
fail: if (mapping)
xa_unlock(&mapping->i_pages);
spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
@@ -2831,52 +2832,56 @@ fail: if (mapping)
void free_transhuge_page(struct page *page)
{
struct pglist_data *pgdata = NODE_DATA(page_to_nid(page));
+ struct deferred_split *ds_queue = &pgdata->deferred_split_queue;
unsigned long flags;
- spin_lock_irqsave(&pgdata->split_queue_lock, flags);
+ spin_lock_irqsave(&ds_queue->split_queue_lock, flags);
if (!list_empty(page_deferred_list(page))) {
- pgdata->split_queue_len--;
+ ds_queue->split_queue_len--;
list_del(page_deferred_list(page));
}
- spin_unlock_irqrestore(&pgdata->split_queue_lock, flags);
+ spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags);
free_compound_page(page);
}
void deferred_split_huge_page(struct page *page)
{
struct pglist_data *pgdata = NODE_DATA(page_to_nid(page));
+ struct deferred_split *ds_queue = &pgdata->deferred_split_queue;
unsigned long flags;
VM_BUG_ON_PAGE(!PageTransHuge(page), page);
- spin_lock_irqsave(&pgdata->split_queue_lock, flags);
+ spin_lock_irqsave(&ds_queue->split_queue_lock, flags);
if (list_empty(page_deferred_list(page))) {
count_vm_event(THP_DEFERRED_SPLIT_PAGE);
- list_add_tail(page_deferred_list(page), &pgdata->split_queue);
- pgdata->split_queue_len++;
+ list_add_tail(page_deferred_list(page), &ds_queue->split_queue);
+ ds_queue->split_queue_len++;
}
- spin_unlock_irqrestore(&pgdata->split_queue_lock, flags);
+ spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags);
}
static unsigned long deferred_split_count(struct shrinker *shrink,
struct shrink_control *sc)
{
struct pglist_data *pgdata = NODE_DATA(sc->nid);
- return READ_ONCE(pgdata->split_queue_len);
+ struct deferred_split *ds_queue = &pgdata->deferred_split_queue;
+ return READ_ONCE(ds_queue->split_queue_len);
}
static unsigned long deferred_split_scan(struct shrinker *shrink,
struct shrink_control *sc)
{
struct pglist_data *pgdata = NODE_DATA(sc->nid);
+ struct deferred_split *ds_queue = &pgdata->deferred_split_queue;
unsigned long flags;
LIST_HEAD(list), *pos, *next;
struct page *page;
int split = 0;
- spin_lock_irqsave(&pgdata->split_queue_lock, flags);
+ spin_lock_irqsave(&ds_queue->split_queue_lock, flags);
/* Take pin on all head pages to avoid freeing them under us */
- list_for_each_safe(pos, next, &pgdata->split_queue) {
+ list_for_each_safe(pos, next, &ds_queue->split_queue) {
page = list_entry((void *)pos, struct page, mapping);
page = compound_head(page);
if (get_page_unless_zero(page)) {
@@ -2884,12 +2889,12 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
} else {
/* We lost race with put_compound_page() */
list_del_init(page_deferred_list(page));
- pgdata->split_queue_len--;
+ ds_queue->split_queue_len--;
}
if (!--sc->nr_to_scan)
break;
}
- spin_unlock_irqrestore(&pgdata->split_queue_lock, flags);
+ spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags);
list_for_each_safe(pos, next, &list) {
page = list_entry((void *)pos, struct page, mapping);
@@ -2903,15 +2908,15 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
put_page(page);
}
- spin_lock_irqsave(&pgdata->split_queue_lock, flags);
- list_splice_tail(&list, &pgdata->split_queue);
- spin_unlock_irqrestore(&pgdata->split_queue_lock, flags);
+ spin_lock_irqsave(&ds_queue->split_queue_lock, flags);
+ list_splice_tail(&list, &ds_queue->split_queue);
+ spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags);
/*
* Stop shrinker if we didn't split any page, but the queue is empty.
* This can happen if pages were freed under us.
*/
- if (!split && list_empty(&pgdata->split_queue))
+ if (!split && list_empty(&ds_queue->split_queue))
return SHRINK_STOP;
return split;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 67768c56d412c..91d820248690c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6371,9 +6371,11 @@ static unsigned long __init calc_memmap_size(unsigned long spanned_pages,
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static void pgdat_init_split_queue(struct pglist_data *pgdat)
{
- spin_lock_init(&pgdat->split_queue_lock);
- INIT_LIST_HEAD(&pgdat->split_queue);
- pgdat->split_queue_len = 0;
+ struct deferred_split *ds_queue = &pgdat->deferred_split_queue;
+
+ spin_lock_init(&ds_queue->split_queue_lock);
+ INIT_LIST_HEAD(&ds_queue->split_queue);
+ ds_queue->split_queue_len = 0;
}
#else
static void pgdat_init_split_queue(struct pglist_data *pgdat) {}
--
2.25.1
1
5
Andreas Kemnade (1):
ARM: OMAP2+: omap_device: fix idling of devices during probe
Arnd Bergmann (4):
wil6210: select CONFIG_CRC32
block: rsxx: select CONFIG_CRC32
lightnvm: select CONFIG_CRC32
wan: ds26522: select CONFIG_BITREVERSE
Ayush Sawal (6):
chtls: Fix hardware tid leak
chtls: Remove invalid set_tcb call
chtls: Fix panic when route to peer not configured
chtls: Replace skb_dequeue with skb_peek
chtls: Added a check to avoid NULL pointer dereference
chtls: Fix chtls resources release sequence
Chris Wilson (1):
drm/i915: Fix mismatch between misplaced vma check and vma insert
Christophe JAILLET (2):
net/sonic: Fix some resource leaks in error handling paths
dmaengine: mediatek: mtk-hsdma: Fix a resource leak in the error
handling path of the probe function
Chunyan Zhang (1):
i2c: sprd: use a specific timeout to avoid system hang up issue
Colin Ian King (1):
cpufreq: powernow-k8: pass policy rather than use cpufreq_cpu_get()
Dan Carpenter (1):
regmap: debugfs: Fix a reversed if statement in regmap_debugfs_init()
Dinghao Liu (3):
iommu/intel: Fix memleak in intel_irq_remapping_alloc
net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
net/mlx5e: Fix two double free cases
Fenghua Yu (2):
x86/resctrl: Use an IPI instead of task_work_add() to update PQR_ASSOC
MSR
x86/resctrl: Don't move a task to the same resource group
Florian Westphal (2):
net: ip: always refragment ip defragmented packets
net: fix pmtu check in nopmtudisc mode
Greg Kroah-Hartman (1):
Linux 4.19.168
Jakub Kicinski (1):
net: vlan: avoid leaks on register_vlan_dev() failures
Jouni K. Seppänen (1):
net: cdc_ncm: correct overhead in delayed_ndp_size
Lorenzo Bianconi (1):
iio: imu: st_lsm6dsx: fix edge-trigger interrupts
Lukas Wunner (1):
spi: pxa2xx: Fix use-after-free on unbind
Marc Zyngier (1):
KVM: arm64: Don't access PMCR_EL0 when no PMU is available
Ming Lei (1):
block: fix use-after-free in disk_part_iter_next
Nick Desaulniers (1):
vmlinux.lds.h: Add PGO and AutoFDO input sections
Ping Cheng (1):
HID: wacom: Fix memory leakage caused by kfifo_alloc
Roman Guskov (1):
spi: stm32: FIFO threshold level - fix align packet size
Samuel Holland (2):
net: stmmac: dwmac-sun8i: Balance internal PHY resource references
net: stmmac: dwmac-sun8i: Balance internal PHY power
Sean Nyekjaer (1):
iio: imu: st_lsm6dsx: flip irq return logic
Sean Tranchetti (1):
net: ipv6: fib: flush exceptions when purging route
Shravya Kumbham (3):
dmaengine: xilinx_dma: check dma_async_device_register return value
dmaengine: xilinx_dma: fix incompatible param warning in
_child_probe()
dmaengine: xilinx_dma: fix mixed_enum_type coverity warning
Vasily Averin (1):
net: drop bogus skb with CHECKSUM_PARTIAL and offset beyond end of
trimmed packet
Xiaolei Wang (1):
regmap: debugfs: Fix a memory leak when calling regmap_attach_dev
Makefile | 2 +-
arch/arm/mach-omap2/omap_device.c | 8 +-
arch/arm64/kvm/sys_regs.c | 4 +
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 113 ++++++++----------
block/genhd.c | 9 +-
drivers/base/regmap/regmap-debugfs.c | 9 +-
drivers/block/Kconfig | 1 +
drivers/cpufreq/powernow-k8.c | 9 +-
drivers/crypto/chelsio/chtls/chtls_cm.c | 68 ++++-------
drivers/dma/mediatek/mtk-hsdma.c | 1 +
drivers/dma/xilinx/xilinx_dma.c | 11 +-
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +-
drivers/hid/wacom_sys.c | 35 +++++-
drivers/i2c/busses/i2c-sprd.c | 8 +-
.../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 26 +++-
drivers/iommu/intel_irq_remapping.c | 2 +
drivers/lightnvm/Kconfig | 1 +
.../net/ethernet/mellanox/mlx5/core/en_fs.c | 3 +
drivers/net/ethernet/natsemi/macsonic.c | 12 +-
drivers/net/ethernet/natsemi/xtsonic.c | 7 +-
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 58 ++++++---
drivers/net/usb/cdc_ncm.c | 8 +-
drivers/net/wan/Kconfig | 1 +
drivers/net/wireless/ath/wil6210/Kconfig | 1 +
drivers/spi/spi-pxa2xx.c | 3 +-
drivers/spi/spi-stm32.c | 4 +-
include/asm-generic/vmlinux.lds.h | 5 +-
net/8021q/vlan.c | 3 +-
net/core/skbuff.c | 6 +
net/ipv4/ip_output.c | 2 +-
net/ipv4/ip_tunnel.c | 10 +-
net/ipv6/ip6_fib.c | 5 +-
32 files changed, 265 insertions(+), 172 deletions(-)
--
2.25.1
1
43
[PATCH openEuler-1.0-LTS] HID: core: Correctly handle ReportSize being zero
by Yang Yingliang 18 Jan '21
by Yang Yingliang 18 Jan '21
18 Jan '21
From: Marc Zyngier <maz(a)kernel.org>
stable inclusion
from linux-4.19.144
commit abae259fdccc5e41ff302dd80a2b944ce385c970
CVE: CVE-2020-0465
--------------------------------
commit bce1305c0ece3dc549663605e567655dd701752c upstream.
It appears that a ReportSize value of zero is legal, even if a bit
non-sensical. Most of the HID code seems to handle that gracefully,
except when computing the total size in bytes. When fed as input to
memset, this leads to some funky outcomes.
Detect the corner case and correctly compute the size.
Cc: stable(a)vger.kernel.org
Signed-off-by: Marc Zyngier <maz(a)kernel.org>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires(a)gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/hid/hid-core.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 3a359716fb38..3178580db7fa 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1419,6 +1419,17 @@ static void hid_output_field(const struct hid_device *hid,
}
}
+/*
+ * Compute the size of a report.
+ */
+static size_t hid_compute_report_size(struct hid_report *report)
+{
+ if (report->size)
+ return ((report->size - 1) >> 3) + 1;
+
+ return 0;
+}
+
/*
* Create a report. 'data' has to be allocated using
* hid_alloc_report_buf() so that it has proper size.
@@ -1431,7 +1442,7 @@ void hid_output_report(struct hid_report *report, __u8 *data)
if (report->id > 0)
*data++ = report->id;
- memset(data, 0, ((report->size - 1) >> 3) + 1);
+ memset(data, 0, hid_compute_report_size(report));
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->device, report->field[n], data);
}
@@ -1558,7 +1569,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
csize--;
}
- rsize = ((report->size - 1) >> 3) + 1;
+ rsize = hid_compute_report_size(report);
if (rsize > HID_MAX_BUFFER_SIZE)
rsize = HID_MAX_BUFFER_SIZE;
--
2.25.1
1
0
[PATCH kernel-4.19 1/2] ascend: share pool: optimize the big lock for memory processing
by Yang Yingliang 18 Jan '21
by Yang Yingliang 18 Jan '21
18 Jan '21
From: Ding Tianhong <dingtianhong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
The sp_mutex is used to protect all critical path for share pool,
it has serious affected the performance of the the memory alloc
and release interface when there is a lot of process in the same
memory group, it will serious break the scailability of the system,
so add a new read semaphore lock to instead of the big lock for allocation
and release critical path.
The scailability has been greatly improved by this modification.
Show the test result:
number of process: alloc 4M avg time:
Before the patch: 1 32us
3 96us
10 330us
after the patch: 1 32us
3 40us
10 60us
v2: fix some conflicts and clean some code.
Signed-off-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Tang Yizhou <tangyizhou(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/share_pool.h | 5 ++
kernel/fork.c | 4 +-
mm/share_pool.c | 170 ++++++++++++++++++++-----------------
3 files changed, 100 insertions(+), 79 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h
index 70b841d0eb8e..f2d17cb85fa5 100644
--- a/include/linux/share_pool.h
+++ b/include/linux/share_pool.h
@@ -93,6 +93,8 @@ struct sp_group {
unsigned long dvpp_va_start;
unsigned long dvpp_size;
atomic_t use_count;
+ /* protect the group internal elements */
+ struct rw_semaphore rw_lock;
};
struct sp_walk_data {
@@ -238,6 +240,8 @@ extern void *vmalloc_hugepage_user(unsigned long size);
extern void *buff_vzalloc_user(unsigned long size);
extern void *buff_vzalloc_hugepage_user(unsigned long size);
+void sp_exit_mm(struct mm_struct *mm);
+
#else
static inline int sp_group_add_task(int pid, int spg_id)
@@ -400,6 +404,7 @@ static inline void *buff_vzalloc_hugepage_user(unsigned long size)
{
return NULL;
}
+
#endif
#endif /* LINUX_SHARE_POOL_H */
diff --git a/kernel/fork.c b/kernel/fork.c
index d1d8ac083c80..61496b70cfb8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1055,8 +1055,6 @@ static inline void __mmput(struct mm_struct *mm)
{
VM_BUG_ON(atomic_read(&mm->mm_users));
- sp_group_exit(mm);
-
uprobe_clear_state(mm);
exit_aio(mm);
ksm_exit(mm);
@@ -1084,6 +1082,8 @@ void mmput(struct mm_struct *mm)
{
might_sleep();
+ sp_group_exit(mm);
+
if (atomic_dec_and_test(&mm->mm_users))
__mmput(mm);
}
diff --git a/mm/share_pool.c b/mm/share_pool.c
index e326c95104da..27792a641401 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -197,6 +197,16 @@ static bool host_svm_sp_enable = false;
int sysctl_share_pool_hugepage_enable = 1;
+static void free_sp_group(struct sp_group *spg);
+
+static bool sp_group_get(struct sp_group *spg)
+{
+ if (spg_valid(spg) && atomic_inc_not_zero(&spg->use_count))
+ return true;
+
+ return false;
+}
+
static unsigned long spa_size(struct sp_area *spa)
{
return spa->real_size;
@@ -337,7 +347,9 @@ static struct sp_group *__sp_find_spg(int pid, int spg_id)
put_task_struct(tsk);
} else {
+ mutex_lock(&sp_mutex);
spg = idr_find(&sp_group_idr, spg_id);
+ mutex_unlock(&sp_mutex);
}
return spg;
@@ -392,6 +404,8 @@ static struct sp_group *find_or_alloc_sp_group(int spg_id)
INIT_LIST_HEAD(&spg->procs);
INIT_LIST_HEAD(&spg->spa_list);
+ init_rwsem(&spg->rw_lock);
+
ret = idr_alloc(&sp_group_idr, spg, spg_id, spg_id+1,
GFP_KERNEL);
if (ret < 0) {
@@ -422,9 +436,8 @@ static struct sp_group *find_or_alloc_sp_group(int spg_id)
goto out_fput;
}
} else {
- if (!spg_valid(spg))
+ if (!sp_group_get(spg))
return ERR_PTR(-ENODEV);
- atomic_inc(&spg->use_count);
}
return spg;
@@ -607,6 +620,8 @@ int sp_group_add_task(int pid, int spg_id)
}
mm->sp_group = spg;
+
+ down_write(&spg->rw_lock);
/* We reactive the spg even the spg exists already. */
spg->is_alive = true;
list_add_tail(&mm->sp_node, &spg->procs);
@@ -675,11 +690,14 @@ int sp_group_add_task(int pid, int spg_id)
mm->sp_group = NULL;
}
+ up_write(&spg->rw_lock);
out_drop_group:
if (unlikely(ret))
__sp_group_drop_locked(spg);
out_put_mm:
- mmput(mm);
+ /* No need to put the mm if the sp group add this mm success.*/
+ if (unlikely(ret))
+ mmput(mm);
out_put_task:
put_task_struct(tsk);
out_unlock:
@@ -712,44 +730,12 @@ static void spg_exit_unlock(bool unlock)
mutex_unlock(&sp_mutex);
}
-/*
- * Do cleanup when a process exits.
- */
-void sp_group_exit(struct mm_struct *mm)
-{
- bool is_alive = true;
- bool unlock;
-
- /*
- * Nothing to do if this thread group doesn't belong to any sp_group.
- * No need to protect this check with lock because we can add a task
- * to a group if !PF_EXITING.
- */
- if (!mm->sp_group)
- return;
-
- spg_exit_lock(&unlock);
- if (list_is_singular(&mm->sp_group->procs))
- is_alive = mm->sp_group->is_alive = false;
- list_del(&mm->sp_node);
- spg_exit_unlock(unlock);
-
- /*
- * To avoid calling this with sp_mutex held, we first mark the
- * sp_group as dead and then send the notification and then do
- * the real cleanup in sp_group_post_exit().
- */
- if (!is_alive)
- blocking_notifier_call_chain(&sp_notifier_chain, 0,
- mm->sp_group);
-}
-
void sp_group_post_exit(struct mm_struct *mm)
{
struct sp_proc_stat *stat;
bool unlock;
- if (!mm->sp_group)
+ if (!enable_ascend_share_pool || !mm->sp_group)
return;
spg_exit_lock(&unlock);
@@ -1139,8 +1125,6 @@ static void sp_munmap(struct mm_struct *mm, unsigned long addr,
{
int err;
- if (!mmget_not_zero(mm))
- return;
down_write(&mm->mmap_sem);
err = do_munmap(mm, addr, size, NULL);
@@ -1150,7 +1134,6 @@ static void sp_munmap(struct mm_struct *mm, unsigned long addr,
}
up_write(&mm->mmap_sem);
- mmput(mm);
}
/* The caller must hold sp_mutex. */
@@ -1183,8 +1166,6 @@ int sp_free(unsigned long addr)
check_interrupt_context();
- mutex_lock(&sp_mutex);
-
/*
* Access control: a share pool addr can only be freed by another task
* in the same spg or a kthread (such as buff_module_guard_work)
@@ -1217,6 +1198,8 @@ int sp_free(unsigned long addr)
sp_dump_stack();
+ down_read(&spa->spg->rw_lock);
+
__sp_free(spa->spg, spa->va_start, spa_size(spa), NULL);
/* Free the memory of the backing shmem or hugetlbfs */
@@ -1226,6 +1209,9 @@ int sp_free(unsigned long addr)
if (ret)
pr_err("share pool: sp free fallocate failed: %d\n", ret);
+ up_read(&spa->spg->rw_lock);
+
+ mutex_lock(&sp_mutex);
/* pointer stat may be invalid because of kthread buff_module_guard_work */
if (current->mm == NULL) {
kthread_stat.alloc_size -= spa->real_size;
@@ -1236,12 +1222,11 @@ int sp_free(unsigned long addr)
else
BUG();
}
+ mutex_unlock(&sp_mutex);
drop_spa:
__sp_area_drop(spa);
out:
- mutex_unlock(&sp_mutex);
-
sp_try_to_compact();
return ret;
}
@@ -1317,9 +1302,7 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
if (sp_flags & SP_HUGEPAGE_ONLY)
sp_flags |= SP_HUGEPAGE;
- mutex_lock(&sp_mutex);
spg = __sp_find_spg(current->pid, SPG_ID_DEFAULT);
- mutex_unlock(&sp_mutex);
if (!spg) { /* DVPP pass through scene: first call sp_alloc() */
/* mdc scene hack */
if (enable_mdc_default_group)
@@ -1336,14 +1319,16 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
ret);
return ERR_PTR(ret);
}
- mutex_lock(&sp_mutex);
spg = current->mm->sp_group;
} else { /* other scenes */
- mutex_lock(&sp_mutex);
if (spg_id != SPG_ID_DEFAULT) {
+ mutex_lock(&sp_mutex);
/* the caller should be a member of the sp group */
- if (spg != idr_find(&sp_group_idr, spg_id))
+ if (spg != idr_find(&sp_group_idr, spg_id)) {
+ mutex_unlock(&sp_mutex);
goto out;
+ }
+ mutex_unlock(&sp_mutex);
}
}
@@ -1352,6 +1337,7 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
goto out;
}
+ down_read(&spg->rw_lock);
if (sp_flags & SP_HUGEPAGE) {
file = spg->file_hugetlb;
size_aligned = ALIGN(size, PMD_SIZE);
@@ -1376,31 +1362,25 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
unsigned long populate = 0;
struct vm_area_struct *vma;
- if (!mmget_not_zero(mm))
- continue;
-
down_write(&mm->mmap_sem);
mmap_addr = sp_mmap(mm, file, spa, &populate);
if (IS_ERR_VALUE(mmap_addr)) {
up_write(&mm->mmap_sem);
p = (void *)mmap_addr;
__sp_free(spg, sp_addr, size_aligned, mm);
- mmput(mm);
pr_err("share pool: allocation sp mmap failed, ret %ld\n", mmap_addr);
goto out;
}
- p =(void *)mmap_addr; /* success */
+ p = (void *)mmap_addr; /* success */
if (populate == 0) {
up_write(&mm->mmap_sem);
- mmput(mm);
continue;
}
vma = find_vma(mm, sp_addr);
if (unlikely(!vma)) {
up_write(&mm->mmap_sem);
- mmput(mm);
pr_err("share pool: allocation failed due to find %pK vma failure\n",
(void *)sp_addr);
p = ERR_PTR(-EINVAL);
@@ -1461,24 +1441,22 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
size_aligned = ALIGN(size, PAGE_SIZE);
sp_flags &= ~SP_HUGEPAGE;
__sp_area_drop(spa);
- mmput(mm);
goto try_again;
}
}
-
- mmput(mm);
break;
}
- mmput(mm);
}
+out:
+ up_read(&spg->rw_lock);
+
+ mutex_lock(&sp_mutex);
if (!IS_ERR(p)) {
stat = idr_find(&sp_stat_idr, current->mm->sp_stat_id);
if (stat)
stat->alloc_size += size_aligned;
}
-
-out:
mutex_unlock(&sp_mutex);
/* this will free spa if mmap failed */
@@ -1556,10 +1534,6 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
}
}
- if (!mmget_not_zero(mm)) {
- ret_addr = -ESPGMMEXIT;
- goto put_file;
- }
down_write(&mm->mmap_sem);
ret_addr = sp_mmap(mm, file, spa, &populate);
@@ -1604,8 +1578,7 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
put_mm:
up_write(&mm->mmap_sem);
- mmput(mm);
-put_file:
+
if (!spa->spg && file)
fput(file);
@@ -1769,10 +1742,12 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
*/
stat = sp_init_proc_stat(tsk, mm);
if (IS_ERR(stat)) {
+ mutex_unlock(&sp_mutex);
uva = stat;
pr_err("share pool: init proc stat failed, ret %lx\n", PTR_ERR(stat));
goto out_unlock;
}
+ mutex_unlock(&sp_mutex);
spg = __sp_find_spg(pid, SPG_ID_DEFAULT);
if (spg == NULL) {
@@ -1794,6 +1769,7 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
}
if (!vmalloc_area_set_flag(spa, kva_aligned, VM_SHAREPOOL)) {
+ up_read(&spg->rw_lock);
pr_err("share pool: %s: the kva %pK is not valid\n", __func__, (void *)kva_aligned);
goto out_drop_spa;
}
@@ -1808,12 +1784,14 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
goto out_unlock;
}
+ down_read(&spg->rw_lock);
if (enable_share_k2u_spg)
spa = sp_alloc_area(size_aligned, sp_flags, spg, SPA_TYPE_K2SPG);
else
spa = sp_alloc_area(size_aligned, sp_flags, NULL, SPA_TYPE_K2TASK);
if (IS_ERR(spa)) {
+ up_read(&spg->rw_lock);
if (printk_ratelimit())
pr_err("share pool: k2u(spg) failed due to alloc spa failure "
"(potential no enough virtual memory when -75): %ld\n",
@@ -1831,14 +1809,18 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
uva = sp_make_share_kva_to_spg(kva_aligned, spa, spg);
else
uva = sp_make_share_kva_to_task(kva_aligned, spa, mm);
+
+ up_read(&spg->rw_lock);
} else {
/* group is dead, return -ENODEV */
pr_err("share pool: failed to make k2u, sp group is dead\n");
}
if (!IS_ERR(uva)) {
+ mutex_lock(&sp_mutex);
uva = uva + (kva - kva_aligned);
stat->k2u_size += size_aligned;
+ mutex_unlock(&sp_mutex);
} else {
/* associate vma and spa */
if (!vmalloc_area_clr_flag(spa, kva_aligned, VM_SHAREPOOL))
@@ -1849,7 +1831,6 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
out_drop_spa:
__sp_area_drop(spa);
out_unlock:
- mutex_unlock(&sp_mutex);
mmput(mm);
out_put_task:
put_task_struct(tsk);
@@ -2144,7 +2125,6 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
unsigned int page_size;
struct sp_proc_stat *stat;
- mutex_lock(&sp_mutex);
/*
* at first we guess it's a hugepage addr
* we can tolerate at most PMD_SIZE or PAGE_SIZE which is matched in k2u
@@ -2157,7 +2137,7 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
if (printk_ratelimit())
pr_err("share pool: invalid input uva %pK in unshare uva\n",
(void *)uva);
- goto out_unlock;
+ goto out;
}
}
@@ -2259,10 +2239,14 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
goto out_drop_area;
}
+ down_read(&spa->spg->rw_lock);
__sp_free(spa->spg, uva_aligned, size_aligned, NULL);
+ up_read(&spa->spg->rw_lock);
}
sp_dump_stack();
+
+ mutex_lock(&sp_mutex);
/* pointer stat may be invalid because of kthread buff_module_guard_work */
if (current->mm == NULL) {
kthread_stat.k2u_size -= spa->real_size;
@@ -2273,6 +2257,7 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
else
WARN(1, "share_pool: %s: null process stat\n", __func__);
}
+ mutex_unlock(&sp_mutex);
out_clr_flag:
/* deassociate vma and spa */
@@ -2281,8 +2266,7 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
out_drop_area:
__sp_area_drop(spa);
-out_unlock:
- mutex_unlock(&sp_mutex);
+out:
return ret;
}
@@ -2446,7 +2430,7 @@ bool sp_config_dvpp_range(size_t start, size_t size, int device_id, int pid)
check_interrupt_context();
if (device_id < 0 || device_id >= MAX_DEVID || pid < 0 || size <= 0 ||
- size> MMAP_SHARE_POOL_16G_SIZE)
+ size > MMAP_SHARE_POOL_16G_SIZE)
return false;
mutex_lock(&sp_mutex);
@@ -2468,9 +2452,10 @@ EXPORT_SYMBOL_GPL(sp_config_dvpp_range);
/* Check whether the address belongs to the share pool. */
bool is_sharepool_addr(unsigned long addr)
{
- if (host_svm_sp_enable == false)
- return addr >= MMAP_SHARE_POOL_START && addr < (MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE);
- return addr >= MMAP_SHARE_POOL_START && addr < MMAP_SHARE_POOL_END;
+ if (host_svm_sp_enable == false)
+ return addr >= MMAP_SHARE_POOL_START && addr < (MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE);
+
+ return addr >= MMAP_SHARE_POOL_START && addr < MMAP_SHARE_POOL_END;
}
EXPORT_SYMBOL_GPL(is_sharepool_addr);
@@ -2515,7 +2500,8 @@ int proc_sp_group_state(struct seq_file *m, struct pid_namespace *ns,
return 0;
}
-static void rb_spa_stat_show(struct seq_file *seq) {
+static void rb_spa_stat_show(struct seq_file *seq)
+{
struct rb_node *node;
struct sp_area *spa;
@@ -2814,6 +2800,36 @@ vm_fault_t sharepool_no_page(struct mm_struct *mm,
}
EXPORT_SYMBOL(sharepool_no_page);
+#define MM_WOULD_FREE 2
+
+void sp_group_exit(struct mm_struct *mm)
+{
+ struct sp_group *spg = NULL;
+ bool is_alive = true, unlock;
+
+ if (!enable_ascend_share_pool)
+ return;
+
+ spg = mm->sp_group;
+
+ /* If the mm_users is 2, it means that the mm is ready to be freed
+ because the last owner of this mm is in exiting process.
+ */
+ if (spg_valid(spg) && atomic_read(&mm->mm_users) == MM_WOULD_FREE) {
+ spg_exit_lock(&unlock);
+ down_write(&spg->rw_lock);
+ if (list_is_singular(&spg->procs))
+ is_alive = spg->is_alive = false;
+ list_del(&mm->sp_node);
+ up_write(&spg->rw_lock);
+ if (!is_alive)
+ blocking_notifier_call_chain(&sp_notifier_chain, 0,
+ mm->sp_group);
+ atomic_dec(&mm->mm_users);
+ spg_exit_unlock(unlock);
+ }
+}
+
struct page *sp_alloc_pages(struct vm_struct *area, gfp_t mask,
unsigned int page_order, int node)
{
--
2.25.1
1
1
[PATCH kernel-4.19 1/5] share_pool: Remove redundant null pointer check
by Yang Yingliang 14 Jan '21
by Yang Yingliang 14 Jan '21
14 Jan '21
From: Tang Yizhou <tangyizhou(a)huawei.com>
ascend inclusion
category: bugfix
bugzilla: 46925
CVE: NA
-------------------------------------------------
__sp_area_drop_locked() checks null pointer of spa, so remove null pointer
checks before calling __sp_area_drop_locked().
Reported-by: Cui Bixuan <cuibixuan(a)huawei.com>
Signed-off-by: Tang Yizhou <tangyizhou(a)huawei.com>
Reviewed-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/share_pool.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/mm/share_pool.c b/mm/share_pool.c
index 4316625defac..2cfac4642e0b 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -443,8 +443,7 @@ static void sp_munmap_task_areas(struct mm_struct *mm, struct list_head *stop)
if (&spa->link == stop)
break;
- if (prev)
- __sp_area_drop_locked(prev);
+ __sp_area_drop_locked(prev);
prev = spa;
atomic_inc(&spa->use_count);
@@ -459,8 +458,7 @@ static void sp_munmap_task_areas(struct mm_struct *mm, struct list_head *stop)
spin_lock(&sp_area_lock);
}
- if (prev)
- __sp_area_drop_locked(prev);
+ __sp_area_drop_locked(prev);
spin_unlock(&sp_area_lock);
}
@@ -607,8 +605,7 @@ int sp_group_add_task(int pid, int spg_id)
struct file *file = spa_file(spa);
unsigned long addr;
- if (prev)
- __sp_area_drop_locked(prev);
+ __sp_area_drop_locked(prev);
prev = spa;
atomic_inc(&spa->use_count);
@@ -651,8 +648,7 @@ int sp_group_add_task(int pid, int spg_id)
spin_lock(&sp_area_lock);
}
- if (prev)
- __sp_area_drop_locked(prev);
+ __sp_area_drop_locked(prev);
spin_unlock(&sp_area_lock);
if (unlikely(ret)) {
--
2.25.1
1
4
Adrian Hunter (1):
scsi: ufs-pci: Ensure UFS device is in PowerDown mode for
suspend-to-disk ->poweroff()
Alexey Dobriyan (2):
proc: change ->nlink under proc_subdir_lock
proc: fix lookup in /proc/net subdirectories after setns(2)
Antoine Tenart (4):
net-sysfs: take the rtnl lock when storing xps_cpus
net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
net-sysfs: take the rtnl lock when storing xps_rxqs
net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
Ard Biesheuvel (1):
crypto: ecdh - avoid buffer overflow in ecdh_set_secret()
Arnd Bergmann (1):
usb: gadget: select CONFIG_CRC32
Bard Liao (1):
Revert "device property: Keep secondary firmware node secondary by
type"
Bart Van Assche (2):
scsi: ide: Do not set the RQF_PREEMPT flag for sense requests
scsi: scsi_transport_spi: Set RQF_PM for domain validation commands
Bean Huo (1):
scsi: ufs: Fix wrong print message in dev_err()
Bjørn Mork (2):
net: usb: qmi_wwan: add Quectel EM160R-GL
USB: serial: option: add Quectel EM160R-GL
Chandana Kishori Chiluveru (1):
usb: gadget: configfs: Preserve function ordering after bind failure
Christophe JAILLET (1):
staging: mt7621-dma: Fix a resource leak in an error handling path
Cong Wang (1):
erspan: fix version 1 check in gre_parse_header()
Dan Carpenter (1):
atm: idt77252: call pci_disable_device() on error path
Dan Williams (1):
x86/mm: Fix leak of pmd ptlock
Daniel Palmer (1):
USB: serial: option: add LongSung M5710 module support
David Disseldorp (1):
scsi: target: Fix XCOPY NAA identifier lookup
Dexuan Cui (1):
video: hyperv_fb: Fix the mmap() regression for v5.4.y and older
Dinghao Liu (1):
net: ethernet: Fix memleak in ethoc_probe
Dominique Martinet (1):
kbuild: don't hardcode depmod path
Eddie Hung (1):
usb: gadget: configfs: Fix use-after-free issue with udc_name
Filipe Manana (1):
btrfs: send: fix wrong file path when there is an inode with a pending
rmdir
Florian Fainelli (1):
net: systemport: set dev->max_mtu to UMAC_MAX_MTU_SIZE
Florian Westphal (1):
netfilter: xt_RATEEST: reject non-null terminated string from
userspace
Greg Kroah-Hartman (1):
Linux 4.19.167
Grygorii Strashko (1):
net: ethernet: ti: cpts: fix ethtool output when no ptp_clock
registered
Guillaume Nault (1):
ipv4: Ignore ECN bits for fib lookups in fib_compute_spec_dst()
Hans de Goede (1):
Bluetooth: revert: hci_h5: close serdev device and free hu in h5_close
Heiner Kallweit (1):
r8169: work around power-saving bug on some chip versions
Huang Shijie (1):
lib/genalloc: fix the overflow when size is too big
Jeff Dike (1):
virtio_net: Fix recursive call to cpus_read_lock()
Jerome Brunet (1):
usb: gadget: f_uac2: reset wMaxPacketSize
Johan Hovold (4):
USB: serial: iuu_phoenix: fix DMA from stack
USB: yurex: fix control-URB timeout handling
USB: usblp: fix DMA to stack
USB: serial: keyspan_pda: remove unused variable
John Wang (1):
net/ncsi: Use real net-device for response handler
Kailang Yang (1):
ALSA: hda/realtek - Fix speaker volume control on Lenovo C940
Linus Torvalds (1):
depmod: handle the case of /sbin/depmod without /sbin in PATH
Manish Chopra (1):
qede: fix offload for IPIP tunnel packets
Manish Narani (1):
usb: gadget: u_ether: Fix MTU size mismatch with RX packet size
Michael Grzeschik (1):
USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk
set
Paolo Bonzini (1):
KVM: x86: fix shift out of bounds reported by UBSAN
Randy Dunlap (2):
net: sched: prevent invalid Scell_log shift count
usb: usbip: vhci_hcd: protect shift size
Rasmus Villemoes (2):
ethernet: ucc_geth: fix use-after-free in ucc_geth_remove()
ethernet: ucc_geth: set dev->max_mtu to 1518
Roger Pau Monne (1):
xen/pvh: correctly setup the PV EFI interface for dom0
Roland Dreier (1):
CDC-NCM: remove "connected" log message
Sean Young (1):
USB: cdc-acm: blacklist another IR Droid device
Serge Semin (1):
usb: dwc3: ulpi: Use VStsDone to detect PHY regs access completion
Sriharsha Allenki (1):
usb: gadget: Fix spinlock lockup on usb_function_deactivate
Stefan Chulski (3):
net: mvpp2: Add TCAM entry to drop flow control pause frames
net: mvpp2: prs: fix PPPoE with ipv6 packet parse
net: mvpp2: Fix GoP port 3 Networking Complex Control configurations
Subash Abhinov Kasiviswanathan (1):
netfilter: x_tables: Update remaining dereference to RCU
Sylwester Dziedziuch (1):
i40e: Fix Error I40E_AQ_RC_EINVAL when removing VFs
Takashi Iwai (2):
ALSA: usb-audio: Fix UBSAN warnings for MIDI jacks
ALSA: hda/via: Fix runtime PM for Clevo W35xSS
Tetsuo Handa (1):
USB: cdc-wdm: Fix use after free in service_outstanding_interrupt().
Thinh Nguyen (1):
usb: uas: Add PNY USB Portable SSD to unusual_uas
Vasily Averin (1):
netfilter: ipset: fix shift-out-of-bounds in htable_bits()
Xie He (1):
net: hdlc_ppp: Fix issues when mod_timer is called while timer is
running
Yang Yingliang (1):
USB: gadget: legacy: fix return error code in acm_ms_bind()
Ying-Tsun Huang (1):
x86/mtrr: Correct the range check before performing MTRR type lookups
Yu Kuai (1):
usb: chipidea: ci_hdrc_imx: add missing put_device() call in
usbmisc_get_init_data()
Yunfeng Ye (1):
workqueue: Kick a worker based on the actual activation of delayed
works
Yunjian Wang (3):
tun: fix return value when the number of iovs exceeds MAX_SKB_FRAGS
net: hns: fix return value check in __lb_other_process()
vhost_net: fix ubuf refcount incorrectly when sendmsg fails
Zqiang (1):
usb: gadget: function: printer: Fix a memory leak for interface
descriptor
bo liu (1):
ALSA: hda/conexant: add a new hda codec CX11970
taehyun.cho (1):
usb: gadget: enable super speed plus
Makefile | 4 +-
arch/x86/kernel/cpu/mtrr/generic.c | 6 +-
arch/x86/kvm/mmu.h | 2 +-
arch/x86/mm/pgtable.c | 2 +
arch/x86/xen/efi.c | 12 +-
arch/x86/xen/enlighten_pv.c | 2 +-
arch/x86/xen/enlighten_pvh.c | 4 +
arch/x86/xen/xen-ops.h | 4 +-
crypto/ecdh.c | 3 +-
drivers/atm/idt77252.c | 2 +-
drivers/base/core.c | 2 +-
drivers/bluetooth/hci_h5.c | 8 +-
drivers/ide/ide-atapi.c | 1 -
drivers/ide/ide-io.c | 5 -
drivers/net/ethernet/broadcom/bcmsysport.c | 1 +
drivers/net/ethernet/ethoc.c | 3 +-
drivers/net/ethernet/freescale/ucc_geth.c | 3 +-
.../net/ethernet/hisilicon/hns/hns_ethtool.c | 4 +
drivers/net/ethernet/intel/i40e/i40e.h | 3 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++
.../ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 +-
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +-
.../net/ethernet/marvell/mvpp2/mvpp2_prs.c | 38 +++++-
.../net/ethernet/marvell/mvpp2/mvpp2_prs.h | 2 +-
drivers/net/ethernet/qlogic/qede/qede_fp.c | 5 +
drivers/net/ethernet/realtek/r8169.c | 6 +-
drivers/net/ethernet/ti/cpts.c | 2 +
drivers/net/tun.c | 2 +-
drivers/net/usb/cdc_ncm.c | 3 -
drivers/net/usb/qmi_wwan.c | 1 +
drivers/net/virtio_net.c | 12 +-
drivers/net/wan/hdlc_ppp.c | 7 ++
drivers/scsi/scsi_transport_spi.c | 27 ++--
drivers/scsi/ufs/ufshcd-pci.c | 34 ++++-
drivers/scsi/ufs/ufshcd.c | 2 +-
drivers/staging/mt7621-dma/mtk-hsdma.c | 4 +-
drivers/target/target_core_xcopy.c | 119 ++++++++++--------
drivers/target/target_core_xcopy.h | 1 +
drivers/usb/chipidea/ci_hdrc_imx.c | 6 +-
drivers/usb/class/cdc-acm.c | 4 +
drivers/usb/class/cdc-wdm.c | 16 ++-
drivers/usb/class/usblp.c | 21 +++-
drivers/usb/dwc3/core.h | 1 +
drivers/usb/dwc3/ulpi.c | 2 +-
drivers/usb/gadget/Kconfig | 2 +
drivers/usb/gadget/composite.c | 10 +-
drivers/usb/gadget/configfs.c | 19 ++-
drivers/usb/gadget/function/f_printer.c | 1 +
drivers/usb/gadget/function/f_uac2.c | 69 +++++++---
drivers/usb/gadget/function/u_ether.c | 9 +-
drivers/usb/gadget/legacy/acm_ms.c | 4 +-
drivers/usb/host/xhci.c | 24 ++--
drivers/usb/misc/yurex.c | 3 +
drivers/usb/serial/iuu_phoenix.c | 20 ++-
drivers/usb/serial/keyspan_pda.c | 2 -
drivers/usb/serial/option.c | 3 +
drivers/usb/storage/unusual_uas.h | 7 ++
drivers/usb/usbip/vhci_hcd.c | 2 +
drivers/vhost/net.c | 6 +-
drivers/video/fbdev/hyperv_fb.c | 6 +-
fs/btrfs/send.c | 49 +++++---
fs/proc/generic.c | 55 +++++---
fs/proc/internal.h | 7 ++
fs/proc/proc_net.c | 16 ---
include/linux/proc_fs.h | 8 +-
include/net/red.h | 4 +-
kernel/workqueue.c | 13 +-
lib/genalloc.c | 25 ++--
net/core/net-sysfs.c | 65 ++++++++--
net/ipv4/fib_frontend.c | 2 +-
net/ipv4/gre_demux.c | 2 +-
net/ipv4/netfilter/arp_tables.c | 2 +-
net/ipv4/netfilter/ip_tables.c | 2 +-
net/ipv6/netfilter/ip6_tables.c | 2 +-
net/ncsi/ncsi-rsp.c | 2 +-
net/netfilter/ipset/ip_set_hash_gen.h | 20 +--
net/netfilter/xt_RATEEST.c | 3 +
net/sched/sch_choke.c | 2 +-
net/sched/sch_gred.c | 2 +-
net/sched/sch_red.c | 2 +-
net/sched/sch_sfq.c | 2 +-
scripts/depmod.sh | 2 +
sound/pci/hda/hda_intel.c | 2 -
sound/pci/hda/patch_conexant.c | 1 +
sound/pci/hda/patch_realtek.c | 6 +
sound/pci/hda/patch_via.c | 13 ++
sound/usb/midi.c | 4 +
87 files changed, 624 insertions(+), 278 deletions(-)
--
2.25.1
1
78
Felix Fietkau (1):
Revert "mtd: spinand: Fix OOB read"
Greg Kroah-Hartman (1):
Linux 4.19.166
Jonathan Cameron (2):
iio:imu:bmi160: Fix alignment and data leak issues
iio:magnetometer:mag3110: Fix alignment and data leak issues.
Josh Poimboeuf (1):
kdev_t: always inline major/minor helper functions
Tudor Ambarus (1):
dmaengine: at_hdmac: Substitute kzalloc with kmalloc
Yu Kuai (2):
dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()
dmaengine: at_hdmac: add missing kfree() call in at_dma_xlate()
Makefile | 2 +-
drivers/dma/at_hdmac.c | 11 ++++++++---
drivers/iio/imu/bmi160/bmi160_core.c | 13 +++++++++----
drivers/iio/magnetometer/mag3110.c | 13 +++++++++----
drivers/mtd/nand/spi/core.c | 4 ----
include/linux/kdev_t.h | 22 +++++++++++-----------
6 files changed, 38 insertions(+), 27 deletions(-)
--
2.25.1
1
8
11 Jan '21
From: Fang Lijun <fanglijun3(a)huawei.com>
ascend inclusion
category: bugfix
bugzilla: NA
CVE: NA
-------------------------------------------------
The vm_flags will changed by MAP_CHECKNODE,
so we must use it for output argument.
Fixes: 66bd45db2b03 ("arm64/ascend: mm: Fix arm32 compile warnings")
Signed-off-by: Fang Lijun <fanglijun3(a)huawei.com>
Reviewed-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/mman.h | 7 ++++---
mm/mmap.c | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/linux/mman.h b/include/linux/mman.h
index d35d984c058c..a8ea591faed7 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -76,15 +76,16 @@ static inline int dvpp_mmap_zone(unsigned long addr) { return 0; }
#ifdef CONFIG_COHERENT_DEVICE
#define CHECKNODE_BITS 48
#define CHECKNODE_MASK (~((_AC(1, UL) << CHECKNODE_BITS) - 1))
-static inline void set_vm_checknode(vm_flags_t vm_flags, unsigned long flags)
+static inline void set_vm_checknode(vm_flags_t *vm_flags, unsigned long flags)
{
if (is_set_cdmmask())
- vm_flags |= VM_CHECKNODE | ((((flags >> MAP_HUGE_SHIFT) &
+ *vm_flags |= VM_CHECKNODE | ((((flags >> MAP_HUGE_SHIFT) &
MAP_HUGE_MASK) << CHECKNODE_BITS) & CHECKNODE_MASK);
}
#else
#define CHECKNODE_BITS (0)
-static inline void set_vm_checknode(vm_flags_t vm_flags, unsigned long flags) {}
+static inline void set_vm_checknode(vm_flags_t *vm_flags, unsigned long flags)
+{}
#endif
/*
diff --git a/mm/mmap.c b/mm/mmap.c
index 9dfef56dd0e8..e0399b087430 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1579,7 +1579,7 @@ unsigned long __do_mmap(struct mm_struct *mm, struct file *file,
* hugetlbfs file mmap will use it to check node
*/
if (flags & MAP_CHECKNODE)
- set_vm_checknode(vm_flags, flags);
+ set_vm_checknode(&vm_flags, flags);
addr = __mmap_region(mm, file, addr, len, vm_flags, pgoff, uf);
if (!IS_ERR_VALUE(addr) &&
--
2.25.1
1
4
2
1
[PATCH openEuler-1.0-LTS] HID: core: Sanitize event code and type when mapping input
by Yang Yingliang 08 Jan '21
by Yang Yingliang 08 Jan '21
08 Jan '21
From: Marc Zyngier <maz(a)kernel.org>
stable inclusion
from linux-4.19.144
commit a47b8511d90528c77346597e2012100dfc28cd8c
CVE: CVE-2020-0465
--------------------------------
commit 35556bed836f8dc07ac55f69c8d17dce3e7f0e25 upstream.
When calling into hid_map_usage(), the passed event code is
blindly stored as is, even if it doesn't fit in the associated bitmap.
This event code can come from a variety of sources, including devices
masquerading as input devices, only a bit more "programmable".
Instead of taking the event code at face value, check that it actually
fits the corresponding bitmap, and if it doesn't:
- spit out a warning so that we know which device is acting up
- NULLify the bitmap pointer so that we catch unexpected uses
Code paths that can make use of untrusted inputs can now check
that the mapping was indeed correct and bail out if not.
Cc: stable(a)vger.kernel.org
Signed-off-by: Marc Zyngier <maz(a)kernel.org>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires(a)gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/hid/hid-input.c | 4 ++++
drivers/hid/hid-multitouch.c | 2 ++
include/linux/hid.h | 42 +++++++++++++++++++++++++-----------
3 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index dbb0cbe65fc9..0062b37ef98f 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1125,6 +1125,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
mapped:
+ /* Mapping failed, bail out */
+ if (!bit)
+ return;
+
if (device->driver->input_mapped &&
device->driver->input_mapped(device, hidinput, field, usage,
&bit, &max) < 0) {
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index f9167d0e095c..dfb2548e0052 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -841,6 +841,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
code = BTN_0 + ((usage->hid - 1) & HID_USAGE);
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
+ if (!*bit)
+ return -1;
input_set_capability(hi->input, EV_KEY, code);
return 1;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 8b3e5e8a72fb..bbbe6c0e0e26 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -956,34 +956,49 @@ static inline void hid_device_io_stop(struct hid_device *hid) {
* @max: maximal valid usage->code to consider later (out parameter)
* @type: input event type (EV_KEY, EV_REL, ...)
* @c: code which corresponds to this usage and type
+ *
+ * The value pointed to by @bit will be set to NULL if either @type is
+ * an unhandled event type, or if @c is out of range for @type. This
+ * can be used as an error condition.
*/
static inline void hid_map_usage(struct hid_input *hidinput,
struct hid_usage *usage, unsigned long **bit, int *max,
- __u8 type, __u16 c)
+ __u8 type, unsigned int c)
{
struct input_dev *input = hidinput->input;
-
- usage->type = type;
- usage->code = c;
+ unsigned long *bmap = NULL;
+ unsigned int limit = 0;
switch (type) {
case EV_ABS:
- *bit = input->absbit;
- *max = ABS_MAX;
+ bmap = input->absbit;
+ limit = ABS_MAX;
break;
case EV_REL:
- *bit = input->relbit;
- *max = REL_MAX;
+ bmap = input->relbit;
+ limit = REL_MAX;
break;
case EV_KEY:
- *bit = input->keybit;
- *max = KEY_MAX;
+ bmap = input->keybit;
+ limit = KEY_MAX;
break;
case EV_LED:
- *bit = input->ledbit;
- *max = LED_MAX;
+ bmap = input->ledbit;
+ limit = LED_MAX;
break;
}
+
+ if (unlikely(c > limit || !bmap)) {
+ pr_warn_ratelimited("%s: Invalid code %d type %d\n",
+ input->name, c, type);
+ *bit = NULL;
+ return;
+ }
+
+ usage->type = type;
+ usage->code = c;
+ *max = limit;
+ *bit = bmap;
}
/**
@@ -997,7 +1012,8 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput,
__u8 type, __u16 c)
{
hid_map_usage(hidinput, usage, bit, max, type, c);
- clear_bit(c, *bit);
+ if (*bit)
+ clear_bit(usage->code, *bit);
}
/**
--
2.25.1
1
0
[PATCH openEuler-1.0-LTS] cfg80211: add missing policy for NL80211_ATTR_STATUS_CODE
by Yang Yingliang 08 Jan '21
by Yang Yingliang 08 Jan '21
08 Jan '21
From: Sergey Matyukevich <sergey.matyukevich.os(a)quantenna.com>
stable inclusion
from linux-4.19.108
commit 0fb31bd53a5e27394916758173eb748c5e0dbd47
CVE: CVE-2020-27068
--------------------------------
[ Upstream commit ea75080110a4c1fa011b0a73cb8f42227143ee3e ]
The nl80211_policy is missing for NL80211_ATTR_STATUS_CODE attribute.
As a result, for strictly validated commands, it's assumed to not be
supported.
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os(a)quantenna.com>
Link: https://lore.kernel.org/r/20200213131608.10541-2-sergey.matyukevich.os@quan…
Signed-off-by: Johannes Berg <johannes.berg(a)intel.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
net/wireless/nl80211.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5075fd293feb..de9580f13914 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -323,6 +323,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
[NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
[NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
+ [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
[NL80211_ATTR_PID] = { .type = NLA_U32 },
--
2.25.1
1
0
[PATCH openEuler-1.0-LTS] speakup: Reject setting the speakup line discipline outside of speakup
by Yang Yingliang 08 Jan '21
by Yang Yingliang 08 Jan '21
08 Jan '21
From: Samuel Thibault <samuel.thibault(a)ens-lyon.org>
mainline inclusion
from mainline-v5.10-rc7
commit f0992098cadb4c9c6a00703b66cafe604e178fea
category: bugfix
bugzilla: NA
CVE: CVE-2020-27830
--------------------------------
Speakup exposing a line discipline allows userland to try to use it,
while it is deemed to be useless, and thus uselessly exposes potential
bugs. One of them is simply that in such a case if the line sends data,
spk_ttyio_receive_buf2 is called and crashes since spk_ttyio_synth
is NULL.
This change restricts the use of the speakup line discipline to
speakup drivers, thus avoiding such kind of issues altogether.
Cc: stable(a)vger.kernel.org
Reported-by: Shisong Qin <qinshisong1205(a)gmail.com>
Signed-off-by: Samuel Thibault <samuel.thibault(a)ens-lyon.org>
Tested-by: Shisong Qin <qinshisong1205(a)gmail.com>
Link: https://lore.kernel.org/r/20201129193523.hm3f6n5xrn6fiyyc@function
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
drivers/accessibility/speakup/spk_ttyio.c
[yyl: spk_ttyio.c is in drivers/staging/speakup/ in kernel-4.19]
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/staging/speakup/spk_ttyio.c | 36 ++++++++++++++++++-----------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
index 6c754ddf1257..8bc7db55daeb 100644
--- a/drivers/staging/speakup/spk_ttyio.c
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -47,27 +47,21 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
struct spk_ldisc_data *ldisc_data;
+ if (tty != speakup_tty)
+ /* Somebody tried to use this line discipline outside speakup */
+ return -ENODEV;
+
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
- mutex_lock(&speakup_tty_mutex);
- if (speakup_tty) {
- mutex_unlock(&speakup_tty_mutex);
- return -EBUSY;
- }
- speakup_tty = tty;
ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
- if (!ldisc_data) {
- speakup_tty = NULL;
- mutex_unlock(&speakup_tty_mutex);
+ if (!ldisc_data)
return -ENOMEM;
- }
sema_init(&ldisc_data->sem, 0);
ldisc_data->buf_free = true;
- speakup_tty->disc_data = ldisc_data;
- mutex_unlock(&speakup_tty_mutex);
+ tty->disc_data = ldisc_data;
return 0;
}
@@ -187,9 +181,25 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
tty_unlock(tty);
+ mutex_lock(&speakup_tty_mutex);
+ speakup_tty = tty;
ret = tty_set_ldisc(tty, N_SPEAKUP);
if (ret)
- pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
+ speakup_tty = NULL;
+ mutex_unlock(&speakup_tty_mutex);
+
+ if (!ret)
+ /* Success */
+ return 0;
+
+ pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
+
+ tty_lock(tty);
+ if (tty->ops->close)
+ tty->ops->close(tty, NULL);
+ tty_unlock(tty);
+
+ tty_kclose(tty);
return ret;
}
--
2.25.1
1
0
08 Jan '21
From: Jann Horn <jannh(a)google.com>
mainline inclusion
from mainline-v5.10-rc7
commit 54ffccbf053b5b6ca4f6e45094b942fab92a25fc
category: bugfix
bugzilla: NA
CVE: CVE-2020-29661
--------------------------------
tiocspgrp() takes two tty_struct pointers: One to the tty that userspace
passed to ioctl() (`tty`) and one to the TTY being changed (`real_tty`).
These pointers are different when ioctl() is called with a master fd.
To properly lock real_tty->pgrp, we must take real_tty->ctrl_lock.
This bug makes it possible for racing ioctl(TIOCSPGRP, ...) calls on
both sides of a PTY pair to corrupt the refcount of `struct pid`,
leading to use-after-free errors.
Fixes: 47f86834bbd4 ("redo locking of tty->pgrp")
CC: stable(a)kernel.org
Signed-off-by: Jann Horn <jannh(a)google.com>
Reviewed-by: Jiri Slaby <jirislaby(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/tty/tty_jobctrl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c
index c4ecd66fafef..a42dec3c95d0 100644
--- a/drivers/tty/tty_jobctrl.c
+++ b/drivers/tty/tty_jobctrl.c
@@ -494,10 +494,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
if (session_of_pgrp(pgrp) != task_session(current))
goto out_unlock;
retval = 0;
- spin_lock_irq(&tty->ctrl_lock);
+ spin_lock_irq(&real_tty->ctrl_lock);
put_pid(real_tty->pgrp);
real_tty->pgrp = get_pid(pgrp);
- spin_unlock_irq(&tty->ctrl_lock);
+ spin_unlock_irq(&real_tty->ctrl_lock);
out_unlock:
rcu_read_unlock();
return retval;
--
2.25.1
1
1
[PATCH openEuler-1.0-LTS] ALSA: rawmidi: Fix racy buffer resize under concurrent accesses
by Yang Yingliang 08 Jan '21
by Yang Yingliang 08 Jan '21
08 Jan '21
From: Takashi Iwai <tiwai(a)suse.de>
stable inclusion
from linux-4.19.124
commit a507658fdb2ad8ca282b0eb42f2a40b805deb1e6
CVE: CVE-2020-27786
--------------------------------
commit c1f6e3c818dd734c30f6a7eeebf232ba2cf3181d upstream.
The rawmidi core allows user to resize the runtime buffer via ioctl,
and this may lead to UAF when performed during concurrent reads or
writes: the read/write functions unlock the runtime lock temporarily
during copying form/to user-space, and that's the race window.
This patch fixes the hole by introducing a reference counter for the
runtime buffer read/write access and returns -EBUSY error when the
resize is performed concurrently against read/write.
Note that the ref count field is a simple integer instead of
refcount_t here, since the all contexts accessing the buffer is
basically protected with a spinlock, hence we need no expensive atomic
ops. Also, note that this busy check is needed only against read /
write functions, and not in receive/transmit callbacks; the race can
happen only at the spinlock hole mentioned in the above, while the
whole function is protected for receive / transmit callbacks.
Reported-by: butt3rflyh4ck <butterflyhuangxx(a)gmail.com>
Cc: <stable(a)vger.kernel.org>
Link: https://lore.kernel.org/r/CAFcO6XMWpUVK_yzzCpp8_XP7+=oUpQvuBeCbMffEDkpe8jWr…
Link: https://lore.kernel.org/r/s5heerw3r5z.wl-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai(a)suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/sound/rawmidi.h | 1 +
sound/core/rawmidi.c | 31 +++++++++++++++++++++++++++----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 6665cb29e1a2..7a908a81cef4 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -76,6 +76,7 @@ struct snd_rawmidi_runtime {
size_t avail_min; /* min avail for wakeup */
size_t avail; /* max used buffer for wakeup */
size_t xruns; /* over/underruns counter */
+ int buffer_ref; /* buffer reference count */
/* misc */
spinlock_t lock;
wait_queue_head_t sleep;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index a52d6d16efc4..9b26973fe697 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -112,6 +112,17 @@ static void snd_rawmidi_input_event_work(struct work_struct *work)
runtime->event(runtime->substream);
}
+/* buffer refcount management: call with runtime->lock held */
+static inline void snd_rawmidi_buffer_ref(struct snd_rawmidi_runtime *runtime)
+{
+ runtime->buffer_ref++;
+}
+
+static inline void snd_rawmidi_buffer_unref(struct snd_rawmidi_runtime *runtime)
+{
+ runtime->buffer_ref--;
+}
+
static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime;
@@ -661,6 +672,11 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime,
if (!newbuf)
return -ENOMEM;
spin_lock_irq(&runtime->lock);
+ if (runtime->buffer_ref) {
+ spin_unlock_irq(&runtime->lock);
+ kvfree(newbuf);
+ return -EBUSY;
+ }
oldbuf = runtime->buffer;
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
@@ -960,8 +976,10 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
long result = 0, count1;
struct snd_rawmidi_runtime *runtime = substream->runtime;
unsigned long appl_ptr;
+ int err = 0;
spin_lock_irqsave(&runtime->lock, flags);
+ snd_rawmidi_buffer_ref(runtime);
while (count > 0 && runtime->avail) {
count1 = runtime->buffer_size - runtime->appl_ptr;
if (count1 > count)
@@ -980,16 +998,19 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
if (userbuf) {
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_to_user(userbuf + result,
- runtime->buffer + appl_ptr, count1)) {
- return result > 0 ? result : -EFAULT;
- }
+ runtime->buffer + appl_ptr, count1))
+ err = -EFAULT;
spin_lock_irqsave(&runtime->lock, flags);
+ if (err)
+ goto out;
}
result += count1;
count -= count1;
}
+ out:
+ snd_rawmidi_buffer_unref(runtime);
spin_unlock_irqrestore(&runtime->lock, flags);
- return result;
+ return result > 0 ? result : err;
}
long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
@@ -1261,6 +1282,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
return -EAGAIN;
}
}
+ snd_rawmidi_buffer_ref(runtime);
while (count > 0 && runtime->avail > 0) {
count1 = runtime->buffer_size - runtime->appl_ptr;
if (count1 > count)
@@ -1292,6 +1314,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
}
__end:
count1 = runtime->avail < runtime->buffer_size;
+ snd_rawmidi_buffer_unref(runtime);
spin_unlock_irqrestore(&runtime->lock, flags);
if (count1)
snd_rawmidi_output_trigger(substream, 1);
--
2.25.1
1
0
hulk inclusion
category: bugfix
bugzilla: 46923
CVE: NA
----------------------------------------------
Enable KTASK in vfio, if the BAR size of some straight through
equipment device is too large, it will cause guest crash on booting.
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Xie XiuQi <xiexiuqi(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
init/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/init/Kconfig b/init/Kconfig
index 6880b55901bb..71b09d998413 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -352,7 +352,7 @@ config AUDIT_TREE
config KTASK
bool "Multithread CPU-intensive kernel work"
depends on SMP
- default y
+ default n
help
Parallelize CPU-intensive kernel work. This feature is designed for
big machines that can take advantage of their extra CPUs to speed up
--
2.25.1
1
4
[PATCH kernel-4.19 01/33] irqchip/gic-v3: Fix compiling error on ARM32 with GICv3
by Yang Yingliang 08 Jan '21
by Yang Yingliang 08 Jan '21
08 Jan '21
From: Wei Li <liwei391(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
----------------------------------------------
/builds/1mHAjaH6WFVPAq6OVOJsJsJKHA2/drivers/irqchip/irq-gic-v3.c: In function 'gic_cpu_init':
/builds/1mHAjaH6WFVPAq6OVOJsJsJKHA2/drivers/irqchip/irq-gic-v3.c:888:3: error: implicit declaration of function 'ipi_set_nmi_prio' [-Werror=implicit-function-declaration]
888 | ipi_set_nmi_prio(rbase, GICD_INT_NMI_PRI);
| ^~~~~~~~~~~~~~~~
On ARM32, ipi_set_nmi_prio() is not implmented as CONFIG_ARM64_PSEUDO_NMI
is not supported. Skip setting the NMI priority of SGIs when initializing.
Signed-off-by: Wei Li <liwei391(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/irqchip/irq-gic-v3.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 6bb787ba1764..14e9c1a5627b 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -884,8 +884,10 @@ static void gic_cpu_init(void)
gic_cpu_config(rbase, gic_redist_wait_for_rwp);
+#ifdef CONFIG_ARM64_PSEUDO_NMI
if (gic_supports_nmi())
ipi_set_nmi_prio(rbase, GICD_INT_NMI_PRI);
+#endif
/* initialise system registers */
gic_cpu_sys_reg_init();
--
2.25.1
1
32
Anant Thazhemadam (2):
Bluetooth: hci_h5: close serdev device and free hu in h5_close
misc: vmw_vmci: fix kernel info-leak by initializing dbells in
vmci_ctx_get_chkpt_doorbells()
Boqun Feng (1):
fcntl: Fix potential deadlock in send_sig{io, urg}()
Christophe Leroy (1):
powerpc/bitops: Fix possible undefined behaviour with fls() and
fls64()
Damien Le Moal (1):
null_blk: Fix zone size initialization
Dinghao Liu (1):
rtc: sun6i: Fix memleak in sun6i_rtc_clk_init
Eric Auger (1):
vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
Eric Biggers (4):
fscrypt: add fscrypt_is_nokey_name()
ext4: prevent creating duplicate encrypted filenames
f2fs: prevent creating duplicate encrypted filenames
ubifs: prevent creating duplicate encrypted filenames
Greg Kroah-Hartman (1):
Linux 4.19.165
Hyeongseok Kim (1):
dm verity: skip verity work if I/O error when system is shutting down
Jan Kara (2):
ext4: don't remount read-only with errors=continue on reboot
quota: Don't overflow quota file offsets
Jessica Yu (1):
module: delay kobject uevent until after module init call
Johan Hovold (1):
of: fix linker-section match-table corruption
Kevin Vigor (1):
md/raid10: initialize r10_bio->read_slot before use.
Mauro Carvalho Chehab (1):
media: gp8psk: initialize stats at power control logic
Miroslav Benes (1):
module: set MODULE_STATE_GOING state when a module fails to load
Paolo Bonzini (2):
KVM: SVM: relax conditions for allowing MSR_IA32_SPEC_CTRL accesses
KVM: x86: reinstate vendor-agnostic check on SPEC_CTRL cpuid bits
Petr Vorel (1):
uapi: move constants from <linux/kernel.h> to <linux/const.h>
Qinglang Miao (1):
powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe()
Rustam Kovhaev (1):
reiserfs: add check for an invalid ih_entry_count
Souptick Joarder (1):
xen/gntdev.c: Mark pages as dirty
Takashi Iwai (3):
ALSA: seq: Use bool for snd_seq_queue internal flags
ALSA: rawmidi: Access runtime->avail always in spinlock
ALSA: pcm: Clear the full allocated memory at hw_params
Trond Myklebust (1):
NFSv4: Fix a pNFS layout related use-after-free race when freeing the
inode
Makefile | 2 +-
arch/powerpc/include/asm/bitops.h | 23 +++++++++++-
arch/powerpc/sysdev/mpic_msgr.c | 2 +-
arch/x86/kvm/cpuid.h | 14 +++++++
arch/x86/kvm/svm.c | 9 ++---
arch/x86/kvm/vmx.c | 6 +--
drivers/block/null_blk_zoned.c | 20 ++++++----
drivers/bluetooth/hci_h5.c | 8 +++-
drivers/md/dm-verity-target.c | 12 +++++-
drivers/md/raid10.c | 3 +-
drivers/media/usb/dvb-usb/gp8psk.c | 2 +-
drivers/misc/vmw_vmci/vmci_context.c | 2 +-
drivers/rtc/rtc-sun6i.c | 8 ++--
drivers/vfio/pci/vfio_pci.c | 3 +-
drivers/xen/gntdev.c | 17 ++++++---
fs/crypto/hooks.c | 10 ++---
fs/ext4/namei.c | 3 ++
fs/ext4/super.c | 15 +++-----
fs/f2fs/f2fs.h | 2 +
fs/fcntl.c | 10 +++--
fs/nfs/nfs4super.c | 2 +-
fs/nfs/pnfs.c | 33 ++++++++++++++++-
fs/nfs/pnfs.h | 5 +++
fs/quota/quota_tree.c | 8 ++--
fs/reiserfs/stree.c | 6 +++
fs/ubifs/dir.c | 17 +++++++--
include/linux/fscrypt_notsupp.h | 5 +++
include/linux/fscrypt_supp.h | 29 +++++++++++++++
include/linux/of.h | 1 +
include/uapi/linux/const.h | 5 +++
include/uapi/linux/ethtool.h | 2 +-
include/uapi/linux/kernel.h | 9 +----
include/uapi/linux/lightnvm.h | 2 +-
include/uapi/linux/mroute6.h | 2 +-
include/uapi/linux/netfilter/x_tables.h | 2 +-
include/uapi/linux/netlink.h | 2 +-
include/uapi/linux/sysctl.h | 2 +-
kernel/module.c | 6 ++-
sound/core/pcm_native.c | 9 ++++-
sound/core/rawmidi.c | 49 ++++++++++++++++++-------
sound/core/seq/seq_queue.h | 8 ++--
41 files changed, 274 insertions(+), 101 deletions(-)
--
2.25.1
1
30
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
The specifier of __init added to hrd_flashProbe() isn't appropriate.
It can cause following building warning:
WARNING: drivers/mtd/hisilicon/sfc/hi-sfc.o(.text.unlikely+0x38c): Section mismatch in reference from the \
function flash_map_init() to the function .init.text:hrd_flashProbe()
The function flash_map_init() references
the function __init hrd_flashProbe().
This is often because flash_map_init lacks a __init
annotation or the annotation of hrd_flashProbe is wrong.
Fixes: 25d711e7ffb7 ("drivers: add sfc driver to hulk")
Signed-off-by: Zhengyuan Liu <liuzhengyuan(a)tj.kylinos.cn>
---
drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c b/drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c
index 23254e325a85..69fb1b306f0d 100644
--- a/drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c
+++ b/drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c
@@ -87,8 +87,8 @@ static int _hrd_flashProbe(const char **mtdDrv, struct map_info *map,
return HRD_ERR;
}
-static int __init hrd_flashProbe(const char **mtdDrv, struct map_info *map,
- struct resource *sfc_regres, struct mtd_info **mtd)
+static int hrd_flashProbe(const char **mtdDrv, struct map_info *map,
+ struct resource *sfc_regres, struct mtd_info **mtd)
{
int ret;
--
2.20.1
3
2
04 Jan '21
From: Zhengyuan Liu <liuzhengyuan(a)tj.kylinos.cn>
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
MAP_PA32BIT was defined in uapi/asm-generic/mman.h, that was not
automatically included by mm/mmap.c when building on platforms such as
mips, and result in following compiling error:
mm/mmap.c: In function ‘do_mmap’:
mm/mmap.c:1450:14: error: ‘MAP_PA32BIT’ undeclared (first use in this function); did you mean ‘MAP_32BIT’?
if (flags & MAP_PA32BIT)
^~~~~~~~~~~
MAP_32BIT
mm/mmap.c:1450:14: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [scripts/Makefile.build:303: mm/mmap.o] Error 1
Fixes: e138253f2b82 ("svm: add support for allocing memory which is within 4G physical address in svm_mmap")
Signed-off-by: Zhengyuan Liu <liuzhengyuan(a)tj.kylinos.cn>
Signed-off-by: Bixuan Cui <cuibixuan(a)huawei.com>
---
arch/alpha/include/uapi/asm/mman.h | 1 +
arch/mips/include/uapi/asm/mman.h | 1 +
arch/parisc/include/uapi/asm/mman.h | 1 +
arch/powerpc/include/uapi/asm/mman.h | 1 +
arch/sparc/include/uapi/asm/mman.h | 1 +
arch/xtensa/include/uapi/asm/mman.h | 1 +
6 files changed, 6 insertions(+)
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index f9d4e6b6d4bd..b3acfc00c8ec 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -33,6 +33,7 @@
#define MAP_STACK 0x80000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x100000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x200000/* MAP_FIXED which doesn't unmap underlying mapping */
+#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_SYNC 2 /* synchronous memory sync */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 3035ca499cd8..72a00c746e78 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -51,6 +51,7 @@
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
/*
* Flags for msync
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 870fbf8c7088..9e989d649e85 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -27,6 +27,7 @@
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
#define MS_SYNC 1 /* synchronous memory sync */
#define MS_ASYNC 2 /* sync memory asynchronously */
diff --git a/arch/powerpc/include/uapi/asm/mman.h b/arch/powerpc/include/uapi/asm/mman.h
index 65065ce32814..95f884ada96f 100644
--- a/arch/powerpc/include/uapi/asm/mman.h
+++ b/arch/powerpc/include/uapi/asm/mman.h
@@ -29,6 +29,7 @@
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
/* Override any generic PKEY permission defines */
#define PKEY_DISABLE_EXECUTE 0x4
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
index f6f99ec65bb3..0d1881b8f30d 100644
--- a/arch/sparc/include/uapi/asm/mman.h
+++ b/arch/sparc/include/uapi/asm/mman.h
@@ -26,6 +26,7 @@
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
#endif /* _UAPI__SPARC_MMAN_H__ */
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index 58f29a9d895d..f584a590bb00 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -58,6 +58,7 @@
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
* uninitialized */
--
2.17.1
3
2
[PATCH kernel-4.19 01/12] memcg/ascend: Check sysctl oom config for memcg oom
by Yang Yingliang 04 Jan '21
by Yang Yingliang 04 Jan '21
04 Jan '21
From: Zhou Guanghui <zhouguanghui1(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
--------------------------------------------------
If memcg oom_kill_disable is false(enable oom killer), and sysctl
enable_oom_killer is also false(disable oom killer), the memory
allocated for this memcg will exceed the limit. This means that
the memcg cannot limit the memory usage.
Therefore, ensure that sysctl enable_oom_killer is not false.
Otherwise, wait for memory resources.
Signed-off-by: Zhou Guanghui <zhouguanghui1(a)huawei.com>
Reviewed-by: Ding Tianhong <dingtianhong(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/memcontrol.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6ad8fafcdf87..aa8f6f75eea1 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1942,7 +1942,11 @@ bool mem_cgroup_oom_synchronize(bool handle)
if (locked)
mem_cgroup_oom_notify(memcg);
- if (locked && !memcg->oom_kill_disable) {
+ if (locked &&
+#ifdef CONFIG_ASCEND_OOM
+ sysctl_enable_oom_killer != 0 &&
+#endif
+ !memcg->oom_kill_disable) {
mem_cgroup_unmark_under_oom(memcg);
finish_wait(&memcg_oom_waitq, &owait.wait);
mem_cgroup_out_of_memory(memcg, current->memcg_oom_gfp_mask,
--
2.25.1
1
11
本次MPAM特性合入59个补丁,主要包括:
1)MPAM 对外sysfs功能增强;
2)适配后续社区版本,适配兼容MPAM协议;
3)代码框架整体重构,拓展对SMMU io的支持;
4)支持鲲鹏930全套MPAM能力;
James Morse (10):
arm64/mpam: Add mpam driver discovery phase and kbuild boiler plate
cacheinfo: Provide a helper to find a cacheinfo leaf
arm64/mpam: Probe supported partid/pmg ranges from devices
arm64/mpam: Supplement MPAM MSC register layout definitions
arm64/mpam: Probe the features resctrl supports
arm64/mpam: Reset controls when CPUs come online
arm64/mpam: Summarize feature support during mpam_enable()
arm64/mpam: resctrl: Re-synchronise resctrl's view of online CPUs
drivers: base: cacheinfo: Add helper to search cacheinfo by of_node
arm64/mpam: Enabling registering and logging error interrupts
Wang ShaoBo (49):
arm64/mpam: Preparing for MPAM refactoring
arm64/mpam: Add helper for getting mpam sysprops
arm64/mpam: Allocate mpam component configuration arrays
arm64/mpam: Pick MPAM resources and events for resctrl_res exported
arm64/mpam: Init resctrl resources' info from resctrl_res selected
arm64/mpam: resctrl: Handle cpuhp and resctrl_dom allocation
arm64/mpam: Implement helpers for handling configuration and
monitoring
arm64/mpam: Migrate old MSCs' discovery process to new branch
arm64/mpam: Add helper for getting MSCs' configuration
arm64/mpam: Probe partid,pmg and feature capabilities' ranges from
classes
arm64/mpam: resctrl: Rebuild configuration and monitoring pipeline
arm64/mpam: resctrl: Append schemata CDP definitions
arm64/mpam: resctrl: Supplement cdpl2,cdpl3 for mount options
arm64/mpam: resctrl: Add helpers for init and destroy schemata list
arm64/mpam: resctrl: Use resctrl_group_init_alloc() to init schema
list
arm64/mpam: resctrl: Write and read schemata by schema_list
arm64/mpam: Support cdp in mpam_sched_in()
arm64/mpam: resctrl: Update resources reset process
arm64/mpam: resctrl: Update closid alloc and free process with bitmap
arm64/mpam: resctrl: Move ctrlmon sysfile write/read function to
mpam_ctrlmon.c
arm64/mpam: Support cdp on allocating monitors
arm64/mpam: resctrl: Support cdp on monitoring data
arm64/mpam: Clean up header files and rearrange declarations
arm64/mpam: resctrl: Remove ctrlmon sysfile
arm64/mpam: resctrl: Remove unnecessary CONFIG_ARM64
arm64/mpam: Implement intpartid narrowing process
arm64/mpam: Using software-defined id for rdtgroup instead of 32-bit
integer
arm64/mpam: resctrl: collect child mon group's monitor data
arm64/mpam: resctrl: Support cpus' monitoring for mon group
arm64/mpam: resctrl: Support priority and hardlimit(Memory bandwidth)
configuration
arm64/mpam: Store intpri and dspri for mpam device reset
arm64/mpam: Squash default priority from mpam device to class
arm64/mpam: Restore extend ctrls' max width for checking schemata
input
arm64/mpam: Re-plan intpartid narrowing process
arm64/mpam: Add hook-events id for ctrl features
arm64/mpam: Integrate monitor data for Memory Bandwidth if cdp enabled
arm64/mpam: Fix MPAM_ESR intPARTID_range error
arm64/mpam: Separate internal and downstream priority event
arm64/mpam: Remap reqpartid,pmg to rmid and intpartid to closid
arm64/mpam: Add wait queue for monitor alloc and free
arm64/mpam: Add resctrl_ctrl_feature structure to manage ctrl features
arm64/mpam: resctrl: Export resource's properties to info directory
arm64/mpam: Split header files into suitable location
arm64/mpam: resctrl: Add rmid file in resctrl sysfs
arm64/mpam: Filter schema control type with ctrl features
arm64/mpam: Simplify mpamid cdp mapping process
arm64/mpam: Set per-cpu's closid to none zero for cdp
ACPI/MPAM: Use acpi_map_pxm_to_node() to get node id for memory node
arm64/mpam: Supplement additional useful ctrl features for mount
options
arch/arm64/include/asm/mpam.h | 324 +---
arch/arm64/include/asm/mpam_resource.h | 129 --
arch/arm64/include/asm/mpam_sched.h | 8 -
arch/arm64/include/asm/resctrl.h | 489 +++++-
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/mpam.c | 1494 ----------------
arch/arm64/kernel/mpam/Makefile | 3 +
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 957 ++++++++++
arch/arm64/kernel/mpam/mpam_device.c | 1706 ++++++++++++++++++
arch/arm64/kernel/mpam/mpam_device.h | 140 ++
arch/arm64/kernel/mpam/mpam_internal.h | 345 ++++
arch/arm64/kernel/mpam/mpam_mon.c | 331 ++++
arch/arm64/kernel/mpam/mpam_resctrl.c | 2221 ++++++++++++++++++++++++
arch/arm64/kernel/mpam/mpam_resource.h | 228 +++
arch/arm64/kernel/mpam/mpam_setup.c | 597 +++++++
arch/arm64/kernel/mpam_ctrlmon.c | 619 -------
arch/arm64/kernel/mpam_mon.c | 121 --
drivers/acpi/arm64/mpam.c | 87 +-
drivers/base/cacheinfo.c | 38 +
fs/resctrlfs.c | 410 +++--
include/linux/arm_mpam.h | 118 ++
include/linux/cacheinfo.h | 36 +
include/linux/resctrlfs.h | 30 -
23 files changed, 7473 insertions(+), 2960 deletions(-)
delete mode 100644 arch/arm64/include/asm/mpam_resource.h
delete mode 100644 arch/arm64/kernel/mpam.c
create mode 100644 arch/arm64/kernel/mpam/Makefile
create mode 100644 arch/arm64/kernel/mpam/mpam_ctrlmon.c
create mode 100644 arch/arm64/kernel/mpam/mpam_device.c
create mode 100644 arch/arm64/kernel/mpam/mpam_device.h
create mode 100644 arch/arm64/kernel/mpam/mpam_internal.h
create mode 100644 arch/arm64/kernel/mpam/mpam_mon.c
create mode 100644 arch/arm64/kernel/mpam/mpam_resctrl.c
create mode 100644 arch/arm64/kernel/mpam/mpam_resource.h
create mode 100644 arch/arm64/kernel/mpam/mpam_setup.c
delete mode 100644 arch/arm64/kernel/mpam_ctrlmon.c
delete mode 100644 arch/arm64/kernel/mpam_mon.c
create mode 100644 include/linux/arm_mpam.h
--
2.25.1
1
59
04 Jan '21
From: Yan Zhao <yan.y.zhao(a)intel.com>
mainline inclusion
from mainline-v5.6-rc7
commit c0560f51cf77472f4ed113539b0a02ca6cda7961
category: Common features
bugzilla: 46841
CVE: NA
-------------------------------------------------
external user calls vfio_group_get_external_user_from_dev() with a device
pointer to get the VFIO group associated with this device.
The VFIO group is checked to be vialbe and have IOMMU set. Then
container user counter is increased and VFIO group reference is hold
to prevent the VFIO group from disposal before external user exits.
when the external user finishes using of the VFIO group, it calls
vfio_group_put_external_user() to dereference the VFIO group and the
container user counter.
Suggested-by: Alex Williamson <alex.williamson(a)redhat.com>
Signed-off-by: Yan Zhao <yan.y.zhao(a)intel.com>
Signed-off-by: Alex Williamson <alex.williamson(a)redhat.com>
Signed-off-by: Xiaoyang Xu <xuxiaoyang2(a)huawei.com>
Reviewed-by: Xiangyou Xie <xiexiangyou(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/vfio/vfio.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/vfio.h | 2 ++
2 files changed, 40 insertions(+)
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 7a386fb30bf1..34a293318a39 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1759,6 +1759,44 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
}
EXPORT_SYMBOL_GPL(vfio_group_get_external_user);
+/**
+ * External user API, exported by symbols to be linked dynamically.
+ * The external user passes in a device pointer
+ * to verify that:
+ * - A VFIO group is assiciated with the device;
+ * - IOMMU is set for the group.
+ * If both checks passed, vfio_group_get_external_user_from_dev()
+ * increments the container user counter to prevent the VFIO group
+ * from disposal before external user exits and returns the pointer
+ * to the VFIO group.
+ *
+ * When the external user finishes using the VFIO group, it calls
+ * vfio_group_put_external_user() to release the VFIO group and
+ * decrement the container user counter.
+ *
+ * @dev [in] : device
+ * Return error PTR or pointer to VFIO group.
+ */
+
+struct vfio_group *vfio_group_get_external_user_from_dev(struct device *dev)
+{
+ struct vfio_group *group;
+ int ret;
+
+ group = vfio_group_get_from_dev(dev);
+ if (!group)
+ return ERR_PTR(-ENODEV);
+
+ ret = vfio_group_add_container_user(group);
+ if (ret) {
+ vfio_group_put(group);
+ return ERR_PTR(ret);
+ }
+
+ return group;
+}
+EXPORT_SYMBOL_GPL(vfio_group_get_external_user_from_dev);
+
void vfio_group_put_external_user(struct vfio_group *group)
{
vfio_group_try_dissolve_container(group);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 66741ab087c1..a1e8943b7be3 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -97,6 +97,8 @@ extern void vfio_unregister_iommu_driver(
*/
extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
extern void vfio_group_put_external_user(struct vfio_group *group);
+extern struct vfio_group *vfio_group_get_external_user_from_dev(struct device
+ *dev);
extern bool vfio_external_group_match_file(struct vfio_group *group,
struct file *filep);
extern int vfio_external_user_iommu_id(struct vfio_group *group);
--
2.25.1
1
9
Alan Stern (1):
media: gspca: Fix memory leak in probe
Alexander Sverdlin (1):
serial: 8250_omap: Avoid FIFO corruption caused by MDR1 access
Alexandre Belloni (1):
ARM: dts: at91: at91sam9rl: fix ADC triggers
Alexey Kardashevskiy (1):
serial_core: Check for port state when tty is in error state
Amadej Kastelic (1):
ALSA: usb-audio: Add VID to support native DSD reproduction on FiiO
devices
Anant Thazhemadam (1):
Bluetooth: hci_h5: fix memory leak in h5_close
Andy Lutomirski (1):
x86/membarrier: Get rid of a dubious optimization
Andy Shevchenko (2):
pinctrl: merrifield: Set default bias in case no particular value
given
pinctrl: baytrail: Avoid clearing debounce value when turning it off
Anmol Karn (1):
Bluetooth: Fix null pointer dereference in hci_event_packet()
Ansuel Smith (1):
PCI: qcom: Add missing reset for ipq806x
Anton Ivanov (3):
um: Monitor error events in IRQ controller
um: tty: Fix handling of close in tty lines
um: chan_xterm: Fix fd leak
Antti Palosaari (1):
media: msi2500: assign SPI bus number dynamically
Ard Biesheuvel (2):
ARM: p2v: fix handling of LPAE translation in BE mode
crypto: ecdh - avoid unaligned accesses in ecdh_set_secret()
Arnd Bergmann (7):
kbuild: avoid static_assert for genksyms
scsi: megaraid_sas: Check user-provided offsets
RDMa/mthca: Work around -Wenum-conversion warning
seq_buf: Avoid type mismatch for seq_buf_init
watchdog: coh901327: add COMMON_CLK dependency
Input: cyapa_gen6 - fix out-of-bounds stack access
platform/x86: mlx-platform: remove an unused variable
Artem Lapkin (1):
arm64: dts: meson: fix spi-max-frequency on Khadas VIM2
Arvind Sankar (3):
x86/mm/mem_encrypt: Fix definition of PMD_FLAGS_DEC_WP
compiler.h: fix barrier_data() on clang
x86/mm/ident_map: Check for errors from ident_pud_init()
Athira Rajeev (1):
powerpc/perf: Exclude kernel samples while counting events in user
space.
Baruch Siach (1):
gpio: mvebu: fix potential user-after-free on probe
Bean Huo (1):
mmc: block: Fixup condition for CMD13 polling for RPMB requests
Bharat Gooty (1):
PCI: iproc: Fix out-of-bound array accesses
Bjorn Andersson (1):
slimbus: qcom-ngd-ctrl: Avoid sending power requests without QMI
Bjorn Helgaas (1):
PCI: Bounds-check command-line resource alignment requests
Björn Töpel (1):
ixgbe: avoid premature Rx buffer reuse
Bob Pearson (1):
RDMA/rxe: Compute PSN windows correctly
Bongsu Jeon (1):
nfc: s3fwrn5: Release the nfc firmware
Borislav Petkov (1):
EDAC/amd64: Fix PCI component registration
Bui Quang Minh (1):
USB: dummy-hcd: Fix uninitialized array use in init()
Calum Mackay (1):
lockd: don't use interval-based rebinding over TCP
Can Guo (1):
scsi: ufs: Make sure clk scaling happens only when HBA is runtime
ACTIVE
Carlos Garnacho (1):
platform/x86: intel-vbtn: Allow switch events on Acer Switch Alpha 12
Cezary Rojewski (1):
ASoC: pcm: DRAIN support reactivation
Chen-Yu Tsai (2):
arm64: dts: rockchip: Set dr_mode to "host" for OTG on rk3328-roc-cc
arm64: dts: rockchip: Fix UART pull-ups on rk3328
Cheng Lin (1):
nfs_common: need lock during iterate through the list
Chris Chiu (4):
Input: i8042 - add Acer laptops to the i8042 reset list
ALSA: hda/realtek - Enable headset mic of ASUS X430UN with ALC256
ALSA: hda/realtek - Enable headset mic of ASUS Q524UQK with ALC255
ALSA: hda/realtek: Apply jack fixup for Quanta NL3
Chris Packham (1):
ARM: dts: Remove non-existent i2c1 from 98dx3236
Christophe JAILLET (5):
ath10k: Fix an error handling path
ath10k: Release some resources in an error handling path
net: bcmgenet: Fix a resource leak in an error handling path in the
probe functin
net: allwinner: Fix some resources leak in the error handling path of
the probe and in the remove function
clk: s2mps11: Fix a resource leak in error handling paths in the probe
function
Christophe Leroy (4):
crypto: talitos - Endianess in current_desc_hdr()
crypto: talitos - Fix return type of current_desc_hdr()
powerpc/feature: Fix CPU_FTRS_ALWAYS by removing CPU_FTRS_GENERIC_32
powerpc/xmon: Change printk() to pr_cont()
Chuhong Yuan (1):
ASoC: jz4740-i2s: add missed checks for clk_get()
Chunguang Xu (1):
ext4: fix a memory leak of ext4_free_data
Chunyan Zhang (1):
gpio: eic-sprd: break loop when getting NULL device resource
Claudiu Beznea (1):
ARM: dts: at91: sama5d2: map securam as device
Coiby Xu (1):
pinctrl: amd: remove debounce filter setting in IRQ type setting
Colin Ian King (3):
crypto: inside-secure - Fix sizeof() mismatch
media: tm6000: Fix sizeof() mismatches
PCI: Fix overflow in command-line resource alignment requests
Connor McAdams (1):
ALSA: hda/ca0132 - Change Input Source enum strings.
Cristian Birsan (2):
ARM: dts: at91: sama5d4_xplained: add pincontrol for USB Host
ARM: dts: at91: sama5d3_xplained: add pincontrol for USB Host
Dae R. Jeong (1):
md: fix a warning caused by a race between concurrent md_ioctl()s
Dan Carpenter (6):
scsi: be2iscsi: Revert "Fix a theoretical leak in
beiscsi_create_eqs()"
soc: renesas: rmobile-sysc: Fix some leaks in
rmobile_init_pm_domains()
media: max2175: fix max2175_set_csm_mode() error code
media: saa7146: fix array overflow in vidioc_s_audio()
ASoC: wm_adsp: remove "ctl" from list on error in
wm_adsp_create_control()
qlcnic: Fix error code in probe
Dan Williams (1):
libnvdimm/namespace: Fix reaping of invalidated block-window-namespace
labels
Daniel Scally (1):
Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources
walks"
Daniel T. Lee (1):
samples: bpf: Fix lwt_len_hist reusing previous BPF map
David Hildenbrand (2):
powerpc/powernv/memtrace: Don't leak kernel memory to user space
powerpc/powernv/memtrace: Fix crashing the kernel when enabling
concurrently
David Jander (1):
Input: ads7846 - fix race that causes missing releases
David Woodhouse (1):
x86/apic: Fix x2apic enablement without interrupt remapping
Deepak R Varma (1):
drm/tegra: replace idr_init() by idr_init_base()
Dmitry Baryshkov (1):
drm/msm/dsi_pll_10nm: restore VCO rate during restore_state
Dmitry Osipenko (1):
clk: tegra: Fix duplicated SE clock entry
Dmitry Torokhov (3):
Input: cm109 - do not stomp on control URB
Input: ads7846 - fix unaligned access on 7845
Input: cros_ec_keyb - send 'scancodes' in addition to key events
Dongdong Wang (1):
lwt: Disable BH too in run_lwt_bpf()
Douglas Anderson (1):
soc: qcom: geni: More properly switch to DMA mode
Dwaipayan Ray (1):
checkpatch: fix unescaped left brace
Eric Biggers (1):
crypto: af_alg - avoid undefined behavior accessing salg_name
Eric Dumazet (2):
mac80211: mesh: fix mesh_pathtbl_init() error path
tcp: select sane initial rcvq_space.space for big MSS
Evan Green (1):
soc: qcom: smp2p: Safely acquire spinlock without IRQs
Fabio Estevam (1):
usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to
imx6ul
Fangrui Song (2):
x86/lib: Change .weak to SYM_FUNC_START_WEAK for
arch/x86/lib/mem*_64.S
arm64: Change .weak to SYM_FUNC_START_WEAK_PI for
arch/arm64/lib/mem*.S
Fugang Duan (2):
net: stmmac: free tx skb buffer in stmmac_resume()
net: stmmac: delete the eee_ctrl_timer after napi disabled
Geert Uytterhoeven (1):
clk: renesas: r9a06g032: Drop __packed for portability
Greg Kroah-Hartman (1):
Linux 4.19.164
Guenter Roeck (1):
watchdog: sirfsoc: Add missing dependency on HAS_IOMEM
H. Nikolaus Schaller (1):
ARM: dts: pandaboard: fix pinmux for gpio user button of Pandaboard ES
Hans de Goede (3):
platform/x86: thinkpad_acpi: Do not report SW_TABLET_MODE on Yoga 11e
platform/x86: thinkpad_acpi: Add BAT1 is primary battery quirk for
Thinkpad Yoga 11e 4th gen
power: supply: axp288_charger: Fix HP Pavilion x2 10 DMI matching
Hao Si (1):
soc: fsl: dpio: Get the cpumask through cpumask_of(cpu)
Hui Wang (1):
ACPI: PNP: compare the string length in the matching_id()
Ian Abbott (1):
staging: comedi: mf6x4: Fix AI end-of-conversion detection
Icenowy Zheng (1):
ARM: dts: sun8i: v3s: fix GIC node memory range
Jack Pham (1):
usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
Jack Xu (1):
crypto: qat - fix status check in qat_hal_put_rel_rd_xfer()
James Morse (1):
x86/resctrl: Remove unused struct mbm_state::chunks_bw
James Smart (2):
scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc()
scsi: lpfc: Re-fix use after free in lpfc_rq_buf_free()
Jan Kara (2):
quota: Sanity-check quota file headers on load
ext4: fix deadlock with fs freezing and EA inodes
Jason Gunthorpe (1):
vfio-pci: Use io_remap_pfn_range() for PCI IO memory
Jernej Skrabec (1):
clk: sunxi-ng: Make sure divider tables have sentinel
Jerome Brunet (1):
ASoC: meson: fix COMPILE_TEST error
Jing Xiangfeng (3):
staging: gasket: interrupt: fix the missed eventfd_ctx_put() in
gasket_interrupt.c
HSI: omap_ssi: Don't jump to free ID in ssi_add_controller()
memstick: r592: Fix error return in r592_probe()
Joel Stanley (1):
ARM: dts: aspeed: s2600wf: Fix VGA memory region location
Johan Hovold (9):
USB: serial: option: add interface-number sanity check to flag
handling
USB: serial: mos7720: fix parallel-port state restore
USB: serial: digi_acceleport: fix write-wakeup deadlocks
USB: serial: keyspan_pda: fix dropped unthrottle interrupts
USB: serial: keyspan_pda: fix write deadlock
USB: serial: keyspan_pda: fix stalled writes
USB: serial: keyspan_pda: fix write-wakeup use-after-free
USB: serial: keyspan_pda: fix tx-unthrottle use-after-free
USB: serial: keyspan_pda: fix write unthrottling
Johannes Berg (2):
iwlwifi: pcie: limit memory read spin time
mac80211: don't set set TDLS STA bandwidth wider than possible
Johannes Thumshirn (1):
block: factor out requeue handling from dispatch code
Jonathan Cameron (4):
iio:light:rpr0521: Fix timestamp alignment and prevent data leak.
iio:light:st_uvis25: Fix timestamp alignment and prevent data leak.
iio:pressure:mpl3115: Force alignment of buffer
iio:imu:bmi160: Fix too large a buffer.
Jordan Niethe (1):
powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
Jubin Zhong (1):
PCI: Fix pci_slot_release() NULL pointer dereference
Julian Sax (1):
HID: i2c-hid: add Vero K147 to descriptor override
Kamal Heib (2):
RDMA/bnxt_re: Set queue pair state when being queried
RDMA/cxgb4: Validate the number of CQEs
Keita Suzuki (1):
media: siano: fix memory leak of debugfs members in smsdvb_hotplug
Keqian Zhu (1):
clocksource/drivers/arm_arch_timer: Correct fault programming of
CNTKCTL_EL1.EVNTI
Krzysztof Kozlowski (4):
ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on
Exynos5410
ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid
XU
drm/tve200: Fix handling of platform_get_irq() error
Leo Yan (2):
perf cs-etm: Change tuple from traceID-CPU# to traceID-metadata
perf cs-etm: Move definition of 'traceid_list' global variable from
header file
Leon Romanovsky (2):
RDMA/cm: Fix an attempt to use non-valid pointer when cleaning
timewait
net/mlx5: Properly convey driver version to firmware
Li Jun (1):
xhci: Give USB2 ports time to enter U3 in bus suspend
Lingling Xu (2):
watchdog: sprd: remove watchdog disable from resume fail path
watchdog: sprd: check busy bit before new loading rather than after
that
Lokesh Vutla (1):
pwm: lp3943: Dynamically allocate PWM chip base
Luc Van Oostenryck (1):
xsk: Fix xsk_poll()'s return type
Luis Henriques (1):
ceph: fix race in concurrent __ceph_remove_cap invocations
Lukas Wunner (8):
spi: bcm2835aux: Fix use-after-free on unbind
media: netup_unidvb: Don't leak SPI master in probe error path
spi: spi-sh: Fix use-after-free on unbind
spi: davinci: Fix use-after-free on unbind
spi: pic32: Don't leak DMA channels in probe error path
spi: rb4xx: Don't leak SPI master in probe error path
spi: sc18is602: Don't leak SPI master in probe error path
spi: st-ssc4: Fix unbalanced pm_runtime_disable() in probe error path
Manivannan Sadhasivam (1):
watchdog: qcom: Avoid context switch in restart handler
Mao Jinlong (1):
coresight: tmc-etr: Check if page is valid before dma_map_page()
Marc Zyngier (3):
genirq/irqdomain: Don't try to free an interrupt that has no mapping
irqchip/alpine-msi: Fix freeing of interrupts on allocation error path
KVM: arm64: Introduce handling of AArch32 TTBCR2 traps
Marek Szyprowski (1):
extcon: max77693: Fix modalias string
Mark Rutland (1):
arm64: syscall: exit userspace before unmasking exceptions
Markus Reichl (1):
arm64: dts: rockchip: Assign a fixed index to mmc devices on rk3399
boards.
Martin Blumenstingl (1):
net: stmmac: dwmac-meson8b: fix mask definition of the m250_sel mux
Martin Wilck (1):
scsi: core: Fix VPD LUN ID designator priorities
Masahiro Yamada (1):
kconfig: fix return value of do_error_if()
Masami Hiramatsu (1):
x86/kprobes: Restore BTF if the single-stepping is cancelled
Mathieu Desnoyers (1):
powerpc: Fix incorrect stw{, ux, u, x} instructions in __set_pte_at
Max Verevkin (1):
platform/x86: intel-vbtn: Support for tablet mode on HP Pavilion 13
x360 PC
Michael Ellerman (1):
powerpc: Drop -me200 addition to build flags
Miquel Raynal (1):
mtd: spinand: Fix OOB read
Moshe Shemesh (2):
net/mlx4_en: Avoid scheduling restart task if it is already running
net/mlx4_en: Handle TX error CQE
Nathan Chancellor (2):
spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
crypto: crypto4xx - Replace bitwise OR with logical OR in
crypto4xx_build_pd
Nathan Lynch (2):
powerpc/pseries/hibernation: drop pseries_suspend_begin() from suspend
ops
powerpc/pseries/hibernation: remove redundant cacheinfo update
Neal Cardwell (1):
tcp: fix cwnd-limited bug for TSO deferral where we send nothing
Necip Fazil Yildiran (1):
MIPS: BCM47XX: fix kconfig dependency bug for BCM47XX_BCMA
NeilBrown (1):
NFS: switch nfsiod to be an UNBOUND workqueue.
Nicholas Piggin (1):
kernel/cpu: add arch override for clear_tasks_mm_cpumask() mm handling
Nick Desaulniers (1):
Kbuild: do not emit debug info for assembly with LLVM_IAS=1
Nicolas Boichat (1):
soc: mediatek: Check if power domains can be powered on at boot time
Nicolas Ferre (1):
ARM: dts: at91: sama5d2: fix CAN message ram offset and size
Nicolin Chen (1):
soc/tegra: fuse: Fix index bug in get_process_id
Nuno Sá (1):
iio: buffer: Fix demux update
Oleksandr Andrushchenko (1):
drm/xen-front: Fix misused IS_ERR_OR_NULL checks
Oleksij Rempel (1):
Input: ads7846 - fix integer overflow on Rt calculation
Olga Kornievskaia (1):
NFSv4.2: condition READDIR's mask for security label based on LSM
state
Oliver Neukum (2):
USB: add RESET_RESUME quirk for Snapscan 1212
USB: UAS: introduce a quirk to set no_write_same
Pali Rohár (5):
cpufreq: highbank: Add missing MODULE_DEVICE_TABLE
cpufreq: mediatek: Add missing MODULE_DEVICE_TABLE
cpufreq: st: Add missing MODULE_DEVICE_TABLE
cpufreq: loongson1: Add missing MODULE_ALIAS
cpufreq: scpi: Add missing MODULE_ALIAS
Paul Kocialkowski (1):
ARM: sunxi: Add machine match for the Allwinner V3 SoC
Paul Moore (1):
selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
Paweł Chmiel (2):
arm64: dts: exynos: Include common syscon restart/poweroff for Exynos7
arm64: dts: exynos: Correct psci compatible used on Exynos7
Peilin Ye (1):
Bluetooth: Fix slab-out-of-bounds read in
hci_le_direct_adv_report_evt()
Peng Liu (1):
sched/deadline: Fix sched_dl_global_validate()
Philipp Rudo (1):
s390/kexec_file: fix diag308 subcode when loading crash kernel
Praveenkumar I (1):
mtd: rawnand: qcom: Fix DMA sync on FLASH_STATUS register read
Qinglang Miao (11):
drm/tegra: sor: Disable clocks on error in tegra_sor_init()
spi: bcm63xx-hsspi: fix missing clk_disable_unprepare() on error in
bcm63xx_hsspi_resume
media: solo6x10: fix missing snd_card_free in error handling case
memstick: fix a double-free bug in memstick_check
cw1200: fix missing destroy_workqueue() on error in cw1200_init_common
mips: cdmm: fix use-after-free in mips_cdmm_bus_discover
platform/x86: dell-smbios-base: Fix error return code in
dell_smbios_init
dm ioctl: fix error return code in target_message
scsi: qedi: Fix missing destroy_workqueue() on error in __qedi_probe
spi: mt7621: fix missing clk_disable_unprepare() on error in
mt7621_spi_probe
iio: adc: rockchip_saradc: fix missing clk_disable_unprepare() on
error in rockchip_saradc_resume
Rafael J. Wysocki (1):
PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()
Rakesh Pillai (1):
ath10k: Fix the parsing error in service available event
Randy Dunlap (1):
scsi: bnx2i: Requires MMU
Richard Weinberger (1):
ubifs: wbuf: Don't leak kernel memory to flash
Roberto Sassu (1):
ima: Don't modify file descriptor mode on the fly
Sakari Ailus (5):
media: ipu3-cio2: Remove traces of returned buffers
media: ipu3-cio2: Return actual subdev format
media: ipu3-cio2: Serialise access to pad format
media: ipu3-cio2: Validate mbus format in setting subdev format
media: ipu3-cio2: Make the field on subdev format V4L2_FIELD_NONE
Sami Tolvanen (1):
arm64: lse: fix LSE atomics with LLVM's integrated assembler
Sara Sharon (2):
iwlwifi: mvm: fix kernel panic in case of assert during CSA
cfg80211: initialize rekey_data
Sean Young (1):
media: sunxi-cir: ensure IR is handled when it is continuous
Sebastian Andrzej Siewior (1):
orinoco: Move context allocation after processing the skb
Serge Hallyn (1):
fix namespaced fscaps when !CONFIG_SECURITY
Sergej Bauer (1):
lan743x: fix for potential NULL pointer dereference with bare card
Simon Beginn (1):
Input: goodix - add upside-down quirk for Teclast X98 Pro tablet
Sreekanth Reddy (1):
scsi: mpt3sas: Increase IOCInit request timeout to 30s
Stefan Haberland (4):
s390/dasd: fix hanging device offline processing
s390/dasd: prevent inconsistent LCU device data
s390/dasd: fix list corruption of pavgroup group list
s390/dasd: fix list corruption of lcu list
Steve French (2):
SMB3: avoid confusing warning message on mount to Azure
SMB3.1.1: do not log warning message if server doesn't populate salt
Steven Rostedt (VMware) (1):
ktest.pl: If size of log is too big to email, email error message
Subash Abhinov Kasiviswanathan (1):
netfilter: x_tables: Switch synchronization to RCU
Sven Eckelmann (3):
vxlan: Add needed_headroom for lower device
vxlan: Copy needed_tailroom from lowerdev
mtd: parser: cmdline: Fix parsing of part-names with colons
Sven Schnelle (1):
s390/smp: perform initial CPU reset also for SMT siblings
Takashi Iwai (7):
ALSA: usb-audio: Fix potential out-of-bounds shift
ALSA: usb-audio: Fix control 'access overflow' errors from chmap
ALSA: pcm: oss: Fix potential out-of-bounds shift
ALSA: hda: Fix regressions on clear and reconfig sysfs
ALSA: pcm: oss: Fix a few more UBSAN fixes
ALSA: hda/realtek: Add quirk for MSI-GP73
ALSA: usb-audio: Disable sample read check if firmware doesn't give
back
Terry Zhou (1):
clk: mvebu: a3700: fix the XTAL MODE pin to MPP1_9
Thomas Gleixner (4):
x86/apic/vector: Fix ordering in vector assignment
USB: sisusbvga: Make console support depend on BROKEN
dm table: Remove BUG_ON(in_interrupt())
sched: Reenable interrupts in do_sched_yield()
Tianyue Ren (1):
selinux: fix error initialization in inode_doinit_with_dentry()
Timo Witte (1):
platform/x86: acer-wmi: add automatic keyboard background light toggle
key as KEY_LIGHTS_TOGGLE
Toke Høiland-Jørgensen (1):
selftests/bpf/test_offload.py: Reset ethtool features after failed
setting
Tom Rix (1):
drm/gma500: fix double free of gma_connector
Trond Myklebust (1):
SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
Tsuchiya Yuto (1):
mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
Tyrel Datwyler (1):
powerpc/rtas: Fix typo of ibm,open-errinjct in RTAS filter
Uwe Kleine-König (2):
spi: fix resource leak for drivers without .remove callback
pwm: zx: Add missing cleanup in error path
Vadim Pasternak (3):
platform/x86: mlx-platform: Remove PSU EEPROM from default platform
configuration
platform/x86: mlx-platform: Remove PSU EEPROM from MSN274x platform
configuration
platform/x86: mlx-platform: Fix item counter assignment for MSN2700,
MSN24xx systems
Vincent Stehlé (2):
powerpc/ps3: use dma_mapping_error()
net: korina: fix return value
Vincenzo Frascino (1):
arm64: lse: Fix LSE atomics with LLVM
Vineet Gupta (1):
ARC: stack unwinding: don't assume non-current task is sleeping
Wang Wensheng (1):
watchdog: Fix potential dereferencing of null pointer
Will McVicker (2):
USB: gadget: f_midi: setup SuperSpeed Plus descriptors
USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
Xiaochen Shen (1):
x86/resctrl: Fix incorrect local bandwidth when mba_sc is enabled
Xin Xiong (1):
drm: fix drm_dp_mst_port refcount leaks in drm_dp_mst_allocate_vcpi
Yang Yingliang (4):
video: fbdev: atmel_lcdfb: fix return error code in
atmel_lcdfb_of_init()
drm/omap: dmm_tiler: fix return error code in omap_dmm_probe()
usb/max3421: fix return error code in max3421_probe()
speakup: fix uninitialized flush_lock
Yangtao Li (1):
pinctrl: sunxi: Always call chained_irq_{enter, exit} in
sunxi_pinctrl_irq_handler
Yu Kuai (3):
media: mtk-vcodec: add missing put_device() call in
mtk_vcodec_release_dec_pm()
clocksource/drivers/cadence_ttc: Fix memory leak in
ttc_setup_clockevent()
pinctrl: falcon: add missing put_device() call in
pinctrl_falcon_probe()
Zhang Changzhong (3):
net: bridge: vlan: fix error return code in __vlan_add()
scsi: fnic: Fix error return code in fnic_probe()
bus: fsl-mc: fix error return code in fsl_mc_object_allocate()
Zhang Qilong (20):
can: softing: softing_netdev_open(): fix error handling
spi: img-spfi: fix reference leak in img_spfi_resume
spi: spi-ti-qspi: fix reference leak in ti_qspi_setup
spi: tegra20-slink: fix reference leak in slink ops of tegra20
spi: tegra20-sflash: fix reference leak in tegra_sflash_resume
spi: tegra114: fix reference leak in tegra spi ops
ASoC: wm8998: Fix PM disable depth imbalance on error
ASoC: arizona: Fix a wrong free in wm8997_probe
staging: greybus: codecs: Fix reference counter leak in error handling
spi: mxs: fix reference leak in mxs_spi_probe
crypto: omap-aes - Fix PM disable depth imbalance in omap_aes_probe
soc: ti: knav_qmss: fix reference leak in knav_queue_probe
soc: ti: Fix reference imbalance in knav_dma_probe
Input: omap4-keypad - fix runtime PM error handling
power: supply: bq24190_charger: fix reference leak
scsi: pm80xx: Fix error return in pm8001_pci_probe()
usb: ehci-omap: Fix PM disable depth umbalance in ehci_hcd_omap_probe
usb: oxu210hp-hcd: Fix memory leak in oxu_create
libnvdimm/label: Return -ENXIO for no slot in __blk_label_update
clk: ti: Fix memleak in ti_fapll_synth_setup
Zhao Heming (2):
md/cluster: block reshape with remote resync job
md/cluster: fix deadlock when node is doing resync job
Zhe Li (1):
jffs2: Fix GC exit abnormally
Zheng Zengkai (1):
perf record: Fix memory leak when using '--user-regs=?' to list
registers
Zhihao Cheng (2):
drivers: soc: ti: knav_qmss_queue: Fix error return code in
knav_queue_probe
dmaengine: mv_xor_v2: Fix error return code in mv_xor_v2_probe()
Zwane Mwaikambo (1):
drm/dp_aux_dev: check aux_dev before use in
drm_dp_aux_dev_get_by_minor()
kazuo ito (1):
nfsd: Fix message level for normal termination
taehyun.cho (1):
USB: gadget: f_acm: add support for SuperSpeed Plus
.../admin-guide/kernel-parameters.txt | 1 +
Makefile | 5 +-
arch/arc/kernel/stacktrace.c | 23 ++--
arch/arm/boot/dts/armada-xp-98dx3236.dtsi | 5 -
.../arm/boot/dts/aspeed-bmc-intel-s2600wf.dts | 4 +-
arch/arm/boot/dts/at91-sama5d3_xplained.dts | 7 +
arch/arm/boot/dts/at91-sama5d4_xplained.dts | 7 +
arch/arm/boot/dts/at91sam9rl.dtsi | 19 +--
arch/arm/boot/dts/exynos5410-odroidxu.dts | 6 +-
arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 28 ++++
arch/arm/boot/dts/exynos5410.dtsi | 4 +
arch/arm/boot/dts/omap4-panda-es.dts | 2 +-
arch/arm/boot/dts/sama5d2.dtsi | 7 +-
arch/arm/boot/dts/sun8i-v3s.dtsi | 2 +-
arch/arm/kernel/head.S | 6 +-
arch/arm/mach-shmobile/pm-rmobile.c | 1 +
arch/arm/mach-sunxi/sunxi.c | 1 +
.../dts/amlogic/meson-gxm-khadas-vim2.dts | 2 +-
arch/arm64/boot/dts/exynos/exynos7.dtsi | 12 +-
.../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 1 +
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 16 +--
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 3 +
arch/arm64/include/asm/atomic_lse.h | 76 ++++++++---
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/include/asm/lse.h | 6 +-
arch/arm64/kernel/syscall.c | 2 +-
arch/arm64/kvm/sys_regs.c | 1 +
arch/arm64/lib/memcpy.S | 3 +-
arch/arm64/lib/memmove.S | 3 +-
arch/arm64/lib/memset.S | 3 +-
arch/mips/bcm47xx/Kconfig | 1 +
arch/powerpc/Makefile | 1 -
arch/powerpc/include/asm/book3s/32/pgtable.h | 4 +-
arch/powerpc/include/asm/cputable.h | 5 -
arch/powerpc/include/asm/nohash/pgtable.h | 4 +-
arch/powerpc/kernel/head_64.S | 8 +-
arch/powerpc/kernel/rtas.c | 2 +-
arch/powerpc/kernel/setup-common.c | 4 +-
arch/powerpc/perf/core-book3s.c | 10 ++
arch/powerpc/platforms/powernv/memtrace.c | 44 +++++-
arch/powerpc/platforms/pseries/suspend.c | 4 -
arch/powerpc/xmon/nonstdio.c | 2 +-
arch/s390/kernel/smp.c | 18 +--
arch/s390/purgatory/head.S | 9 +-
arch/um/drivers/chan_user.c | 4 +-
arch/um/drivers/xterm.c | 5 +
arch/um/os-Linux/irq.c | 2 +-
arch/x86/include/asm/apic.h | 1 +
arch/x86/include/asm/pgtable_types.h | 1 +
arch/x86/include/asm/sync_core.h | 9 +-
arch/x86/kernel/apic/apic.c | 14 +-
arch/x86/kernel/apic/vector.c | 24 ++--
arch/x86/kernel/apic/x2apic_phys.c | 9 ++
arch/x86/kernel/cpu/intel_rdt.h | 2 -
arch/x86/kernel/cpu/intel_rdt_monitor.c | 7 +-
arch/x86/kernel/kprobes/core.c | 5 +
arch/x86/lib/memcpy_64.S | 6 +-
arch/x86/lib/memmove_64.S | 4 +-
arch/x86/lib/memset_64.S | 6 +-
arch/x86/mm/ident_map.c | 12 +-
arch/x86/mm/mem_encrypt_identity.c | 4 +-
arch/x86/mm/tlb.c | 10 +-
block/blk-mq.c | 29 ++--
crypto/af_alg.c | 10 +-
crypto/ecdh.c | 9 +-
drivers/acpi/acpi_pnp.c | 3 +
drivers/acpi/device_pm.c | 41 ++----
drivers/acpi/resource.c | 2 +-
drivers/bluetooth/hci_h5.c | 3 +
drivers/bus/fsl-mc/fsl-mc-allocator.c | 4 +-
drivers/bus/mips_cdmm.c | 4 +-
drivers/clk/clk-s2mps11.c | 1 +
drivers/clk/mvebu/armada-37xx-xtal.c | 4 +-
drivers/clk/renesas/r9a06g032-clocks.c | 2 +-
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 1 +
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 1 +
drivers/clk/tegra/clk-id.h | 1 +
drivers/clk/tegra/clk-tegra-periph.c | 2 +-
drivers/clk/ti/fapll.c | 11 +-
drivers/clocksource/arm_arch_timer.c | 23 +++-
drivers/clocksource/cadence_ttc_timer.c | 18 +--
drivers/cpufreq/highbank-cpufreq.c | 7 +
drivers/cpufreq/loongson1-cpufreq.c | 1 +
drivers/cpufreq/mediatek-cpufreq.c | 1 +
drivers/cpufreq/scpi-cpufreq.c | 1 +
drivers/cpufreq/sti-cpufreq.c | 7 +
drivers/crypto/amcc/crypto4xx_core.c | 2 +-
drivers/crypto/inside-secure/safexcel.c | 2 +-
drivers/crypto/omap-aes.c | 3 +-
drivers/crypto/qat/qat_common/qat_hal.c | 2 +-
drivers/crypto/talitos.c | 10 +-
drivers/dma/mv_xor_v2.c | 4 +-
drivers/edac/amd64_edac.c | 26 ++--
drivers/extcon/extcon-max77693.c | 2 +-
drivers/gpio/gpio-eic-sprd.c | 2 +-
drivers/gpio/gpio-mvebu.c | 16 ++-
drivers/gpu/drm/drm_dp_aux_dev.c | 2 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 7 +-
drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c | 8 ++
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 1 +
drivers/gpu/drm/tegra/drm.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 10 +-
drivers/gpu/drm/tve200/tve200_drv.c | 4 +-
drivers/gpu/drm/xen/xen_drm_front.c | 2 +-
drivers/gpu/drm/xen/xen_drm_front_gem.c | 8 +-
drivers/gpu/drm/xen/xen_drm_front_kms.c | 2 +-
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c | 8 ++
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
.../hwtracing/coresight/coresight-tmc-etr.c | 2 +
drivers/iio/adc/rockchip_saradc.c | 2 +-
drivers/iio/imu/bmi160/bmi160_core.c | 4 +-
drivers/iio/industrialio-buffer.c | 6 +-
drivers/iio/light/rpr0521.c | 17 ++-
drivers/iio/light/st_uvis25.h | 5 +
drivers/iio/light/st_uvis25_core.c | 8 +-
drivers/iio/pressure/mpl3115.c | 9 +-
drivers/infiniband/core/cm.c | 2 +
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 1 +
drivers/infiniband/hw/cxgb4/cq.c | 3 +
drivers/infiniband/hw/mthca/mthca_cq.c | 2 +-
drivers/infiniband/hw/mthca/mthca_dev.h | 1 -
drivers/infiniband/sw/rxe/rxe_req.c | 3 +-
drivers/input/keyboard/cros_ec_keyb.c | 1 +
drivers/input/keyboard/omap4-keypad.c | 89 ++++++++-----
drivers/input/misc/cm109.c | 7 +-
drivers/input/mouse/cyapa_gen6.c | 2 +-
drivers/input/serio/i8042-x86ia64io.h | 42 ++++++
drivers/input/touchscreen/ads7846.c | 52 +++++---
drivers/input/touchscreen/goodix.c | 12 ++
drivers/irqchip/irq-alpine-msi.c | 3 +-
drivers/md/dm-ioctl.c | 1 +
drivers/md/dm-table.c | 6 -
drivers/md/md-cluster.c | 67 ++++++----
drivers/md/md.c | 21 ++-
drivers/media/common/siano/smsdvb-main.c | 5 +-
drivers/media/i2c/max2175.c | 2 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 62 +++++----
drivers/media/pci/intel/ipu3/ipu3-cio2.h | 1 +
.../media/pci/netup_unidvb/netup_unidvb_spi.c | 5 +-
drivers/media/pci/saa7146/mxb.c | 19 +--
drivers/media/pci/solo6x10/solo6x10-g723.c | 2 +-
.../platform/mtk-vcodec/mtk_vcodec_dec_pm.c | 1 +
drivers/media/rc/sunxi-cir.c | 2 +
drivers/media/usb/gspca/gspca.c | 1 +
drivers/media/usb/msi2500/msi2500.c | 2 +-
drivers/media/usb/tm6000/tm6000-video.c | 5 +-
drivers/memstick/core/memstick.c | 1 -
drivers/memstick/host/r592.c | 12 +-
drivers/mmc/core/block.c | 2 +-
drivers/mtd/cmdlinepart.c | 14 +-
drivers/mtd/nand/raw/qcom_nandc.c | 2 +
drivers/mtd/nand/spi/core.c | 4 +
drivers/net/can/softing/softing_main.c | 9 +-
drivers/net/ethernet/allwinner/sun4i-emac.c | 7 +-
.../net/ethernet/broadcom/genet/bcmgenet.c | 4 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 24 +++-
drivers/net/ethernet/korina.c | 2 +-
.../net/ethernet/mellanox/mlx4/en_netdev.c | 21 ++-
drivers/net/ethernet/mellanox/mlx4/en_tx.c | 40 +++++-
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 12 +-
.../net/ethernet/mellanox/mlx5/core/main.c | 6 +-
.../net/ethernet/microchip/lan743x_ethtool.c | 9 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 +
.../ethernet/stmicro/stmmac/dwmac-meson8b.c | 6 +-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 27 +++-
drivers/net/vxlan.c | 3 +
drivers/net/wireless/ath/ath10k/usb.c | 7 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 4 +-
drivers/net/wireless/ath/ath10k/wmi.c | 9 +-
drivers/net/wireless/ath/ath10k/wmi.h | 1 +
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +-
.../net/wireless/intel/iwlwifi/pcie/trans.c | 36 +++--
.../wireless/intersil/orinoco/orinoco_usb.c | 14 +-
drivers/net/wireless/marvell/mwifiex/main.c | 2 +
drivers/net/wireless/st/cw1200/main.c | 2 +
drivers/nfc/s3fwrn5/firmware.c | 4 +-
drivers/nvdimm/label.c | 13 +-
drivers/pci/controller/dwc/pcie-qcom.c | 12 ++
drivers/pci/controller/pcie-iproc.c | 10 +-
drivers/pci/pci-acpi.c | 4 +-
drivers/pci/pci.c | 14 +-
drivers/pci/slot.c | 6 +-
drivers/pinctrl/intel/pinctrl-baytrail.c | 8 +-
drivers/pinctrl/intel/pinctrl-merrifield.c | 8 ++
drivers/pinctrl/pinctrl-amd.c | 7 -
drivers/pinctrl/pinctrl-falcon.c | 14 +-
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 +-
drivers/platform/x86/acer-wmi.c | 1 +
drivers/platform/x86/dell-smbios-base.c | 1 +
drivers/platform/x86/intel-vbtn.c | 12 ++
drivers/platform/x86/mlx-platform.c | 27 +---
drivers/platform/x86/thinkpad_acpi.c | 10 +-
drivers/power/supply/axp288_charger.c | 28 ++--
drivers/power/supply/bq24190_charger.c | 20 ++-
drivers/ps3/ps3stor_lib.c | 2 +-
drivers/pwm/pwm-lp3943.c | 1 +
drivers/pwm/pwm-zx.c | 1 +
drivers/s390/block/dasd_alias.c | 22 ++-
drivers/scsi/be2iscsi/be_main.c | 4 +-
drivers/scsi/bnx2i/Kconfig | 1 +
drivers/scsi/fnic/fnic_main.c | 1 +
drivers/scsi/lpfc/lpfc_mem.c | 6 +-
drivers/scsi/lpfc/lpfc_sli.c | 10 +-
drivers/scsi/megaraid/megaraid_sas_base.c | 16 ++-
drivers/scsi/mpt3sas/mpt3sas_base.c | 2 +-
drivers/scsi/pm8001/pm8001_init.c | 3 +-
drivers/scsi/qedi/qedi_main.c | 4 +-
drivers/scsi/scsi_lib.c | 126 ++++++++++++------
drivers/scsi/ufs/ufshcd.c | 7 +
drivers/slimbus/qcom-ngd-ctrl.c | 6 +
drivers/soc/fsl/dpio/dpio-driver.c | 5 +-
drivers/soc/mediatek/mtk-scpsys.c | 5 +-
drivers/soc/qcom/qcom-geni-se.c | 17 ++-
drivers/soc/qcom/smp2p.c | 5 +-
drivers/soc/tegra/fuse/speedo-tegra210.c | 2 +-
drivers/soc/ti/knav_dma.c | 13 +-
drivers/soc/ti/knav_qmss_queue.c | 4 +-
drivers/spi/spi-bcm2835aux.c | 17 +--
drivers/spi/spi-bcm63xx-hsspi.c | 4 +-
drivers/spi/spi-davinci.c | 2 +-
drivers/spi/spi-img-spfi.c | 4 +-
drivers/spi/spi-mxs.c | 1 +
drivers/spi/spi-pic32.c | 1 +
drivers/spi/spi-rb4xx.c | 2 +-
drivers/spi/spi-sc18is602.c | 13 +-
drivers/spi/spi-sh.c | 13 +-
drivers/spi/spi-st-ssc4.c | 5 +-
drivers/spi/spi-tegra114.c | 2 +
drivers/spi/spi-tegra20-sflash.c | 1 +
drivers/spi/spi-tegra20-slink.c | 2 +
drivers/spi/spi-ti-qspi.c | 1 +
drivers/spi/spi.c | 19 +--
drivers/staging/comedi/drivers/mf6x4.c | 3 +-
drivers/staging/gasket/gasket_interrupt.c | 15 ++-
drivers/staging/greybus/audio_codec.c | 2 +
drivers/staging/mt7621-spi/spi-mt7621.c | 2 +
drivers/staging/speakup/speakup_dectlk.c | 2 +-
drivers/tty/serial/8250/8250_omap.c | 5 -
drivers/tty/serial/serial_core.c | 4 +
drivers/usb/chipidea/ci_hdrc_imx.c | 3 +-
drivers/usb/core/quirks.c | 3 +
drivers/usb/gadget/function/f_acm.c | 2 +-
drivers/usb/gadget/function/f_fs.c | 5 +-
drivers/usb/gadget/function/f_midi.c | 6 +
drivers/usb/gadget/function/f_rndis.c | 4 +-
drivers/usb/gadget/udc/dummy_hcd.c | 2 +-
drivers/usb/host/ehci-omap.c | 1 +
drivers/usb/host/max3421-hcd.c | 3 +-
drivers/usb/host/oxu210hp-hcd.c | 4 +-
drivers/usb/host/xhci-hub.c | 4 +
drivers/usb/misc/sisusbvga/Kconfig | 2 +-
drivers/usb/serial/digi_acceleport.c | 45 ++-----
drivers/usb/serial/keyspan_pda.c | 63 +++++----
drivers/usb/serial/mos7720.c | 2 +
drivers/usb/serial/option.c | 23 +++-
drivers/usb/storage/uas.c | 3 +
drivers/usb/storage/unusual_uas.h | 7 +-
drivers/usb/storage/usb.c | 3 +
drivers/vfio/pci/vfio_pci.c | 4 +-
drivers/video/fbdev/atmel_lcdfb.c | 2 +-
drivers/watchdog/Kconfig | 3 +-
drivers/watchdog/qcom-wdt.c | 2 +-
drivers/watchdog/sprd_wdt.c | 34 +++--
drivers/watchdog/watchdog_core.c | 22 +--
fs/ceph/caps.c | 11 +-
fs/cifs/smb2ops.c | 3 +-
fs/cifs/smb2pdu.c | 7 +-
fs/cifs/smb2pdu.h | 14 +-
fs/ext4/inode.c | 19 ++-
fs/ext4/mballoc.c | 1 +
fs/jffs2/readinode.c | 16 +++
fs/lockd/host.c | 20 +--
fs/nfs/inode.c | 2 +-
fs/nfs/nfs4proc.c | 10 +-
fs/nfs_common/grace.c | 6 +-
fs/nfsd/nfssvc.c | 3 +-
fs/quota/quota_v2.c | 19 +++
fs/ubifs/io.c | 13 +-
include/acpi/acpi_bus.h | 5 -
include/linux/build_bug.h | 5 +
include/linux/compiler-clang.h | 1 -
include/linux/compiler-gcc.h | 19 ---
include/linux/compiler.h | 18 ++-
include/linux/netfilter/x_tables.h | 5 +-
include/linux/security.h | 2 +-
include/linux/seq_buf.h | 2 +-
include/linux/sunrpc/xprt.h | 1 +
include/linux/trace_seq.h | 4 +-
include/linux/usb_usual.h | 2 +
include/uapi/linux/if_alg.h | 16 +++
kernel/cpu.c | 6 +-
kernel/irq/irqdomain.c | 11 +-
kernel/sched/core.c | 6 +-
kernel/sched/deadline.c | 5 +-
kernel/sched/sched.h | 42 +++---
net/bluetooth/hci_event.c | 17 ++-
net/bridge/br_vlan.c | 4 +-
net/core/lwt_bpf.c | 8 +-
net/ipv4/netfilter/arp_tables.c | 14 +-
net/ipv4/netfilter/ip_tables.c | 14 +-
net/ipv4/tcp_input.c | 3 +-
net/ipv4/tcp_output.c | 9 +-
net/ipv6/netfilter/ip6_tables.c | 14 +-
net/mac80211/mesh_pathtbl.c | 4 +-
net/mac80211/vht.c | 14 +-
net/netfilter/x_tables.c | 49 +++----
net/sunrpc/xprt.c | 65 ++++++---
net/sunrpc/xprtrdma/module.c | 1 +
net/sunrpc/xprtrdma/transport.c | 1 +
net/sunrpc/xprtsock.c | 4 +
net/wireless/nl80211.c | 2 +-
net/xdp/xsk.c | 8 +-
samples/bpf/lwt_len_hist.sh | 2 +
samples/bpf/test_lwt_bpf.sh | 0
scripts/checkpatch.pl | 2 +-
scripts/kconfig/preprocess.c | 2 +-
security/integrity/ima/ima_crypto.c | 20 +--
security/selinux/hooks.c | 16 ++-
sound/core/oss/pcm_oss.c | 28 ++--
sound/pci/hda/hda_codec.c | 2 +-
sound/pci/hda/hda_sysfs.c | 2 +-
sound/pci/hda/patch_ca0132.c | 2 +-
sound/pci/hda/patch_realtek.c | 4 +
sound/soc/codecs/wm8997.c | 2 +
sound/soc/codecs/wm8998.c | 4 +-
sound/soc/codecs/wm_adsp.c | 5 +-
sound/soc/jz4740/jz4740-i2s.c | 4 +
sound/soc/meson/Kconfig | 2 +-
sound/soc/soc-pcm.c | 2 +
sound/usb/clock.c | 6 +
sound/usb/format.c | 2 +
sound/usb/quirks.c | 1 +
sound/usb/stream.c | 6 +-
.../perf/util/cs-etm-decoder/cs-etm-decoder.c | 8 +-
tools/perf/util/cs-etm.c | 29 +++-
tools/perf/util/cs-etm.h | 10 +-
tools/perf/util/parse-regs-options.c | 2 +-
tools/testing/ktest/ktest.pl | 7 +-
tools/testing/selftests/bpf/test_offload.py | 1 +
340 files changed, 2021 insertions(+), 1084 deletions(-)
mode change 100644 => 100755 samples/bpf/lwt_len_hist.sh
mode change 100644 => 100755 samples/bpf/test_lwt_bpf.sh
--
2.25.1
1
337
[PATCH v2 1/1 openEuler-1.0-LTS] fork: add pid recover method for checkpoint and recover
by hejingxian 31 Dec '20
by hejingxian 31 Dec '20
31 Dec '20
From: hejingxian <hejingxian(a)huawei.com>
Date: Thu, 31 Dec 2020 20:18:56 +0800
Subject: [PATCH v2 1/1 openEuler-1.0-LTS] fork: add pid recover method for checkpoint and recover
We record the pid of dump task in the reserved memory, and reserve the pids before
init task start. In the recover process, set the fork_pid of the recovery task before
call fork(). And then the fork_pid will be used to alloc pid.
/proc/sys/kernel/ns_last_pid can also be used to fork child task with assigned pid.
However, when there exist many tasks need to recover at the same time, we will fail to
recover pids by using /proc/sys/kernel/ns_last_pid.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
---
drivers/char/pin_memory.c | 24 +++++++++++++++++++++-
include/linux/pin_mem.h | 6 ++++++
include/linux/sched.h | 9 +++++++++
init/init_task.c | 3 +++
kernel/pid.c | 33 ++++++++++++++++++++++++++++++
mm/Kconfig | 7 +++++++
mm/pin_mem.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
index a0464e1..2c65de7 100644
--- a/drivers/char/pin_memory.c
+++ b/drivers/char/pin_memory.c
@@ -36,9 +36,12 @@ struct pin_mem_area_set {
#define _SET_PIN_MEM_AREA 1
#define _CLEAR_PIN_MEM_AREA 2
#define _REMAP_PIN_MEM_AREA 3
+#define _SET_FORK_PID 4
+
#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+#define SET_FORK_PID _IOW(PIN_MEM_MAGIC, _SET_FORK_PID, int)
static int set_pin_mem(struct pin_mem_area_set *pmas)
{
@@ -136,13 +139,29 @@ static int pin_mem_remap(unsigned long arg)
return -EFAULT;
}
+static int set_fork_pid(unsigned long arg)
+{
+ int pid;
+ struct page_map_info * pmi = NULL;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(int)))
+ goto fault;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ goto fault;
+ current->fork_pid = pid;
+ return 0;
+fault:
+ return -EFAULT;
+}
+
static long pin_memory_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
long ret = 0;
if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
return -EINVAL;
- if (_IOC_NR(cmd) > _REMAP_PIN_MEM_AREA)
+ if (_IOC_NR(cmd) > _SET_FORK_PID)
return -EINVAL;
switch (cmd) {
@@ -155,6 +174,9 @@ static long pin_memory_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case REMAP_PIN_MEM_AREA:
ret = pin_mem_remap(arg);
break;
+ case SET_FORK_PID:
+ ret = set_fork_pid(arg);
+ break;
default:
return -EINVAL;
}
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
index 997ddb8..f47dab4 100644
--- a/include/linux/pin_mem.h
+++ b/include/linux/pin_mem.h
@@ -58,5 +58,11 @@ extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned l
#endif
extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+#ifdef CONFIG_PID_RECOVER
+extern bool is_need_reserve_pids(void);
+extern void reserve_pids(struct idr *idr, int pid_max);
+extern void free_reserved_pid(struct idr *idr, int pid);
+#endif
+
#endif /* CONFIG_PIN_MEMORY */
#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ced2d7f..3d23e46 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1220,7 +1220,16 @@ struct task_struct {
KABI_RESERVE(1)
KABI_RESERVE(2)
#endif
+#ifdef CONFIG_PID_RECOVER
+#ifndef __GENKSYMS__
+ int fork_pid;
+ int reserve;
+#else
KABI_RESERVE(3)
+#endif
+#else
+ KABI_RESERVE(3)
+#endif
KABI_RESERVE(4)
KABI_RESERVE(5)
KABI_RESERVE(6)
diff --git a/init/init_task.c b/init/init_task.c
index 5aebe3b..0334ad8 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -179,6 +179,9 @@ struct task_struct init_task
#ifdef CONFIG_SECURITY
.security = NULL,
#endif
+#ifdef CONFIG_PID_RECOVER
+ .fork_pid = 0,
+#endif
};
EXPORT_SYMBOL(init_task);
diff --git a/kernel/pid.c b/kernel/pid.c
index bfdcd16..5d02591 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -41,6 +41,9 @@
#include <linux/sched/task.h>
#include <linux/idr.h>
#include <linux/kmemleak.h>
+#ifdef CONFIG_PID_RECOVER
+#include <linux/pin_mem.h>
+#endif
struct pid init_struct_pid = {
.count = ATOMIC_INIT(1),
@@ -185,6 +188,31 @@ struct pid *alloc_pid(struct pid_namespace *ns)
if (idr_get_cursor(&tmp->idr) > RESERVED_PIDS)
pid_min = RESERVED_PIDS;
+#ifdef CONFIG_PID_RECOVER
+ if (!current->fork_pid) {
+ /*
+ * Store a null pointer so find_pid_ns does not find
+ * a partially initialized PID (see below).
+ */
+ nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
+ tmp->pid_max,
+ GFP_ATOMIC);
+ } else {
+ /* Try to use fork_pid to alloc pid, and change to use the default way after fail. */
+ test_pid_reserved_and_free(&tmp->idr, current->fork_pid);
+ pid_min = current->fork_pid;
+ current->fork_pid = 0;
+ nr = idr_alloc(&tmp->idr, NULL, pid_min,
+ tmp->pid_max,
+ GFP_ATOMIC);
+ pr_debug("Alloc pid by fork_pid ret: %d.", nr);
+ if (nr < 0)
+ nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
+ tmp->pid_max,
+ GFP_ATOMIC);
+ }
+#else
+
/*
* Store a null pointer so find_pid_ns does not find
* a partially initialized PID (see below).
@@ -192,6 +220,7 @@ struct pid *alloc_pid(struct pid_namespace *ns)
nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
tmp->pid_max,
GFP_ATOMIC);
+#endif
spin_unlock_irq(&pidmap_lock);
idr_preload_end();
@@ -500,6 +529,10 @@ void __init pid_idr_init(void)
init_pid_ns.pid_cachep = KMEM_CACHE(pid,
SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT);
+#ifdef CONFIG_PID_RECOVER
+ if (is_need_reserve_pids())
+ reserve_pids(&init_pid_ns.idr, pid_max);
+#endif
hdr = register_sysctl_paths(pid_kern_path, pid_ctl_table);
kmemleak_not_leak(hdr);
diff --git a/mm/Kconfig b/mm/Kconfig
index 31fa670..9ac20da 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -794,4 +794,11 @@ config PIN_MEMORY
help
Say y here to enable the pin memory feature for checkpoint
and restore.
+
+config PID_RECOVER
+ bool "Support for pid recover"
+ depends on PIN_MEMORY
+ help
+ Say y here to enable the pid recover feature for checkpoint
+ and restore.
endmenu
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
index 89af938..2f77e86 100644
--- a/mm/pin_mem.c
+++ b/mm/pin_mem.c
@@ -688,4 +688,55 @@ vm_fault_t reserve_kernel_space_mem(unsigned long start_addr, unsigned int pages
}
EXPORT_SYMBOL_GPL(reserve_kernel_space_mem);
+#ifdef CONFIG_PID_RECOVER
+struct idr *reserve_idr;
+
+/* test if there exist pin memory tasks */
+bool is_need_reserve_pids(void)
+{
+ return (pin_pid_num > 0);
+}
+
+void free_reserved_pid(struct idr *idr, int pid)
+{
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num || idr != reserve_idr)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->pid == pid && pmi->pid_reserved) {
+ idr_remove(idr, pid);
+ return;
+ }
+ }
+}
+
+/* reserve pids for check point tasks which pinned memory */
+void reserve_pids(struct idr *idr, int pid_max)
+{
+ int alloc_pid;
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num)
+ return;
+ reserve_idr = idr;
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pmi->pid_reserved = true;
+ alloc_pid = idr_alloc(idr, NULL, pmi->pid, pid_max, GFP_ATOMIC);
+ if (alloc_pid != pmi->pid) {
+ if (alloc_pid > 0)
+ idr_remove(idr, alloc_pid);
+ pr_warn("Reserve pid (%d) fail, real pid is %d.\n", alloc_pid, pmi->pid);
+ pmi->pid_reserved = false;
+ continue;
+ }
+ }
+ return;
+}
+#endif /* CONFIG_PID_RECOVER */
#endif /* CONFIG_PIN_MEMORY */
--
1.8.3.1
1
0
[PATCH v1 1/1 openEuler-1.0-LTS] fork: add pid recover method for checkpoint and recover
by hejingxian 31 Dec '20
by hejingxian 31 Dec '20
31 Dec '20
From: hejingxian <hejingxian(a)huawei.com>
Date: Thu, 10 Dec 2020 20:35:00 +0800
Subject: [PATCH v1 1/1 openEuler-1.0-LTS] fork: add pid recover method for checkpoint and recover
We record the pid of dump task in the reserved memory, and reserve the pids before
init task start. In the recover process, set the fork_pid of the recovery task before
call fork(). And then the fork_pid will be used to alloc pid.
/proc/sys/kernel/ns_last_pid can also be used to fork child task with assigned pid.
However, when there exist many tasks need to recover at the same time, we will fail to
recover pids by using /proc/sys/kernel/ns_last_pid.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
---
drivers/char/pin_memory.c | 24 +++++++++++++++++++++-
include/linux/pin_mem.h | 6 ++++++
include/linux/sched.h | 4 ++++
init/init_task.c | 3 +++
kernel/pid.c | 27 ++++++++++++++++++++++++-
mm/Kconfig | 7 +++++++
mm/pin_mem.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
index a0464e1..2c65de7 100644
--- a/drivers/char/pin_memory.c
+++ b/drivers/char/pin_memory.c
@@ -36,9 +36,12 @@ struct pin_mem_area_set {
#define _SET_PIN_MEM_AREA 1
#define _CLEAR_PIN_MEM_AREA 2
#define _REMAP_PIN_MEM_AREA 3
+#define _SET_FORK_PID 4
+
#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+#define SET_FORK_PID _IOW(PIN_MEM_MAGIC, _SET_FORK_PID, int)
static int set_pin_mem(struct pin_mem_area_set *pmas)
{
@@ -136,13 +139,29 @@ static int pin_mem_remap(unsigned long arg)
return -EFAULT;
}
+static int set_fork_pid(unsigned long arg)
+{
+ int pid;
+ struct page_map_info * pmi = NULL;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(int)))
+ goto fault;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ goto fault;
+ current->fork_pid = pid;
+ return 0;
+fault:
+ return -EFAULT;
+}
+
static long pin_memory_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
long ret = 0;
if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
return -EINVAL;
- if (_IOC_NR(cmd) > _REMAP_PIN_MEM_AREA)
+ if (_IOC_NR(cmd) > _SET_FORK_PID)
return -EINVAL;
switch (cmd) {
@@ -155,6 +174,9 @@ static long pin_memory_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case REMAP_PIN_MEM_AREA:
ret = pin_mem_remap(arg);
break;
+ case SET_FORK_PID:
+ ret = set_fork_pid(arg);
+ break;
default:
return -EINVAL;
}
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
index 0ca44ac..4162043 100644
--- a/include/linux/pin_mem.h
+++ b/include/linux/pin_mem.h
@@ -58,5 +58,11 @@ extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned l
#endif
extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+#ifdef CONFIG_PID_RECOVER
+extern bool is_need_reserve_pids(void);
+extern void reserve_pids(struct idr *idr, int pid_max);
+extern void free_reserved_pid(struct idr *idr, int pid);
+#endif
+
#endif /* CONFIG_PIN_MEMORY */
#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 716ad1d..f6b1560 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1281,6 +1281,10 @@ struct task_struct {
unsigned long prev_lowest_stack;
#endif
+#ifdef CONFIG_PID_RECOVER
+ int fork_pid;
+#endif
+
/*
* New fields for task_struct should be added above here, so that
* they are included in the randomized portion of task_struct.
diff --git a/init/init_task.c b/init/init_task.c
index 9e5cbe5..40cd98f 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -181,6 +181,9 @@ struct task_struct init_task
#ifdef CONFIG_SECURITY
.security = NULL,
#endif
+#ifdef CONFIG_PID_RECOVER
+ .fork_pid = 0,
+#endif
};
EXPORT_SYMBOL(init_task);
diff --git a/kernel/pid.c b/kernel/pid.c
index 2278e24..dc93f7a 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -42,6 +42,9 @@
#include <linux/sched/signal.h>
#include <linux/sched/task.h>
#include <linux/idr.h>
+#ifdef CONFIG_PID_RECOVER
+#include <linux/pin_mem.h>
+#endif
struct pid init_struct_pid = {
.count = REFCOUNT_INIT(1),
@@ -208,8 +211,26 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
idr_preload(GFP_KERNEL);
spin_lock_irq(&pidmap_lock);
-
+#ifdef CONFIG_PID_RECOVER
+ if (current->fork_pid) {
+ int pid_min;
+ /* Try to free the reserved fork_pid, and then use it to alloc pid. */
+ free_reserved_pid(&tmp->idr, current->fork_pid);
+ pid_min = current->fork_pid;
+ current->fork_pid = 0;
+ nr = idr_alloc(&tmp->idr, NULL, pid_min,
+ pid_min + 1,
+ GFP_ATOMIC);
+ /*
+ * If ENOSPC is returned it means that the PID is
+ * alreay in use. Return EEXIST in that case.
+ */
+ if (nr == -ENOSPC)
+ nr = -EEXIST;
+ } else if (tid) {
+#else
if (tid) {
+#endif
nr = idr_alloc(&tmp->idr, NULL, tid,
tid + 1, GFP_ATOMIC);
/*
@@ -577,4 +598,8 @@ void __init pid_idr_init(void)
init_pid_ns.pid_cachep = KMEM_CACHE(pid,
SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT);
+#ifdef CONFIG_PID_RECOVER
+ if (is_need_reserve_pids())
+ reserve_pids(&init_pid_ns.idr, pid_max);
+#endif
}
diff --git a/mm/Kconfig b/mm/Kconfig
index c2dd088..847e8e4 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -745,4 +745,11 @@ config PIN_MEMORY
help
Say y here to enable the pin memory feature for checkpoint
and restore.
+
+config PID_RECOVER
+ bool "Support for pid recover"
+ depends on PIN_MEMORY
+ help
+ Say y here to enable the pid recover feature for checkpoint
+ and restore.
endmenu
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
index ca3f23a..9426874 100644
--- a/mm/pin_mem.c
+++ b/mm/pin_mem.c
@@ -688,4 +688,55 @@ vm_fault_t reserve_kernel_space_mem(unsigned long start_addr, unsigned int pages
}
EXPORT_SYMBOL_GPL(reserve_kernel_space_mem);
+#ifdef CONFIG_PID_RECOVER
+struct idr *reserve_idr;
+
+/* test if there exist pin memory tasks */
+bool is_need_reserve_pids(void)
+{
+ return (pin_pid_num > 0);
+}
+
+void free_reserved_pid(struct idr *idr, int pid)
+{
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num || idr != reserve_idr)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->pid == pid && pmi->pid_reserved) {
+ idr_remove(idr, pid);
+ return;
+ }
+ }
+}
+
+/* reserve pids for check point tasks which pinned memory */
+void reserve_pids(struct idr *idr, int pid_max)
+{
+ int alloc_pid;
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num)
+ return;
+ reserve_idr = idr;
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pmi->pid_reserved = true;
+ alloc_pid = idr_alloc(idr, NULL, pmi->pid, pid_max, GFP_ATOMIC);
+ if (alloc_pid != pmi->pid) {
+ if (alloc_pid > 0)
+ idr_remove(idr, alloc_pid);
+ pr_warn("Reserve pid (%d) fail, real pid is %d.\n", alloc_pid, pmi->pid);
+ pmi->pid_reserved = false;
+ continue;
+ }
+ }
+ return;
+}
+#endif /* CONFIG_PID_RECOVER */
#endif /* CONFIG_PIN_MEMORY */
--
1.8.3.1
2
1
[PATCH v1 0/1 openEuler-1.0-LTS] mm: add pin memory method for checkpoint add restore
by hejingxian 31 Dec '20
by hejingxian 31 Dec '20
31 Dec '20
From: hejingxian <hejingxian(a)huawei.com>
Date: Thu, 10 Dec 2020 20:31:15 +0800
Subject: [PATCH v1 0/1 openEuler-1.0-LTS] mm: add pin memory method for checkpoint add restore
We can use the checkpoint and restore in userspace(criu) method to dump and restore tasks
when updating the kernel. Currently, criu needs dump all memory data of tasks to files.
When the memory size is very large(larger than 1G), the cost time of the dumping data
will be very long(more than 1 min).
We can pin the memory data of tasks and collect the corresponding physical pages mapping info
in checkpoint process, and remap the physical pages to restore tasks after kernel is updated.
The pin memory area info is saved in the reserve memblock named nvwa_res_first, which can keep
usable in the kernel update process.
The pin memory driver provides the following ioctl command for criu:
1) SET_PIN_MEM_AREA: set pin memory area, which can be remap to the restore task.
2) CLEAR_PIN_MEM_AREA: clear the pin memory area info, which enable user reset the pin data.
3) REMAP_PIN_MEM_AREA: remap the pages of the pin memory to the restore task.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
---
arch/arm64/kernel/setup.c | 7 +
arch/arm64/mm/init.c | 62 +++-
drivers/char/Kconfig | 7 +
drivers/char/Makefile | 1 +
drivers/char/pin_memory.c | 198 +++++++++++++
include/linux/crash_core.h | 5 +
include/linux/pin_mem.h | 62 ++++
kernel/crash_core.c | 11 +
mm/Kconfig | 6 +
mm/Makefile | 1 +
mm/huge_memory.c | 61 ++++
mm/memory.c | 68 +++++
mm/pin_mem.c | 691 +++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 1179 insertions(+), 1 deletion(-)
create mode 100644 drivers/char/pin_memory.c
create mode 100644 include/linux/pin_mem.h
create mode 100644 mm/pin_mem.c
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 56f6645..40751ed 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -50,6 +50,9 @@
#include <asm/efi.h>
#include <asm/xen/hypervisor.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_memory.h>
+#endif
static int num_standard_resources;
static struct resource *standard_resources;
@@ -243,6 +246,10 @@ static void __init request_standard_resources(void)
crashk_res.end <= res->end)
request_resource(res, &crashk_res);
#endif
+#ifdef CONFIG_PIN_MEMORY
+ if (pin_memory_resource.end)
+ insert_resource(&iomem_resource, &pin_memory_resource);
+#endif
}
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b65dffd..dee3192 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -41,7 +41,9 @@
#include <linux/sizes.h>
#include <asm/tlb.h>
#include <asm/alternative.h>
-
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_memory.h>
+#endif
#define ARM64_ZONE_DMA_BITS 30
/*
@@ -68,6 +70,16 @@
phys_addr_t arm64_dma_phys_limit __ro_after_init;
static phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+#ifdef CONFIG_PIN_MEMORY
+struct resource pin_memory_resource = {
+ .name = "Pin memory maps",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PIN_MEM_MAPS
+};
+#endif
+
#ifdef CONFIG_KEXEC_CORE
/*
* reserve_crashkernel() - reserves memory for crash kernel
@@ -129,6 +141,47 @@ static void __init reserve_crashkernel(void)
}
#endif /* CONFIG_KEXEC_CORE */
+#ifdef CONFIG_PIN_MEMORY
+static void __init reserve_pin_memory_res(void)
+{
+ unsigned long long mem_start, mem_len;
+ int ret;
+
+ ret = parse_pin_memory(boot_command_line, memblock_phys_mem_size(),
+ &mem_len, &mem_start);
+ if (ret || !mem_len)
+ return;
+
+ mem_len = PAGE_ALIGN(mem_len);
+
+ if (!memblock_is_region_memory(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region is not memory!\n");
+ return;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n");
+ return;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve for pin memory: base address is not 2MB aligned\n");
+ return;
+ }
+
+ memblock_reserve(mem_start, mem_len);
+ pr_debug("pin memory resource reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ mem_start, mem_start + mem_len, mem_len >> 20);
+
+ pin_memory_resource.start = mem_start;
+ pin_memory_resource.end = mem_start + mem_len - 1;
+}
+#else
+static void __init reserve_pin_memory_res(void)
+{
+}
+#endif /* CONFIG_PIN_MEMORY */
+
#ifdef CONFIG_CRASH_DUMP
static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
const char *uname, int depth, void *data)
@@ -452,6 +505,8 @@ void __init arm64_memblock_init(void)
reserve_crashkernel();
+ reserve_pin_memory_res();
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
@@ -573,6 +628,11 @@ void __init mem_init(void)
/* this will put all unused low memory onto the freelists */
memblock_free_all();
+#ifdef CONFIG_PIN_MEMORY
+ /* pre alloc the pages for pin memory */
+ init_reserve_page_map((unsigned long)pin_memory_resource.start,
+ (unsigned long)(pin_memory_resource.end - pin_memory_resource.start));
+#endif
mem_init_print_info(NULL);
/*
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 26956c0..73af2f0 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -560,3 +560,10 @@ config RANDOM_TRUST_BOOTLOADER
booloader is trustworthy so it will be added to the kernel's entropy
pool. Otherwise, say N here so it will be regarded as device input that
only mixes the entropy pool.
+
+config PIN_MEMORY_DEV
+ bool "/dev/pinmem character device"
+ depends PIN_MEMORY
+ default n
+ help
+ pin memory driver
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f..1941642 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -52,3 +52,4 @@ js-rtc-y = rtc.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
obj-$(CONFIG_ADI) += adi.o
+obj-$(CONFIG_PIN_MEMORY_DEV) += pin_memory.o
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
new file mode 100644
index 00000000..a0464e1
--- /dev/null
+++ b/drivers/char/pin_memory.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright @ Huawei Technologies Co., Ltd. 2020-2020. ALL rights reserved.
+ * Description: Euler pin memory driver
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/mm_types.h>
+#include <asm/processor.h>
+#include <uapi/asm-generic/ioctl.h>
+#include <uapi/asm-generic/mman-common.h>
+#include <uapi/asm/setup.h>
+#include <linux/pin_mem.h>
+#include <linux/sched/mm.h>
+
+#define MAX_PIN_MEM_AREA_NUM 16
+struct _pin_mem_area {
+ unsigned long virt_start;
+ unsigned long virt_end;
+};
+
+struct pin_mem_area_set {
+ unsigned int pid;
+ unsigned int area_num;
+ struct _pin_mem_area mem_area[MAX_PIN_MEM_AREA_NUM];
+};
+
+#define PIN_MEM_MAGIC 0x59
+#define _SET_PIN_MEM_AREA 1
+#define _CLEAR_PIN_MEM_AREA 2
+#define _REMAP_PIN_MEM_AREA 3
+#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
+#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
+#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+
+static int set_pin_mem(struct pin_mem_area_set *pmas)
+{
+ int i;
+ int ret = 0;
+ struct _pin_mem_area *pma;
+ struct mm_struct *mm;
+ struct task_struct *task;
+ struct pid *pid_s;
+
+ pid_s = find_get_pid(pmas->pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pmas->pid);
+ goto fail;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pmas->pid);
+ goto fail;
+ }
+ mm = get_task_mm(task);
+ for (i = 0; i < pmas->area_num; i++) {
+ pma = &(pmas->mem_area[i]);
+ ret = pin_mem_area(task, mm, pma->virt_start, pma->virt_end);
+ if (ret) {
+ mmput(mm);
+ goto fail;
+ }
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ return ret;
+
+fail:
+ rcu_read_unlock();
+ return -EFAULT;
+}
+
+static int set_pin_mem_area(unsigned long arg)
+{
+ struct pin_mem_area_set pmas;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(pmas)))
+ return -EFAULT;
+ if (copy_from_user(&pmas, buf, sizeof(pmas)))
+ return -EINVAL;
+ if (pmas.area_num > MAX_PIN_MEM_AREA_NUM) {
+ pr_warn("Input area_num is too large.\n");
+ return -EINVAL;
+ }
+
+ return set_pin_mem(&pmas);
+}
+
+static int pin_mem_remap(unsigned long arg)
+{
+ int pid;
+ struct task_struct *task;
+ struct mm_struct *mm;
+ vm_fault_t ret;
+ void __user *buf = (void __user *)arg;
+ struct pid *pid_s;
+
+ if (!access_ok(buf, sizeof(int)))
+ return -EINVAL;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ return -EINVAL;
+
+ pid_s = find_get_pid(pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pid);
+ return -EINVAL;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pid);
+ goto fault;
+ }
+ mm = get_task_mm(task);
+ ret = do_mem_remap(pid, mm);
+ if (ret) {
+ pr_warn("Handle pin memory remap fail.\n");
+ mmput(mm);
+ goto fault;
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ return 0;
+
+fault:
+ rcu_read_unlock();
+ return -EFAULT;
+}
+
+static long pin_memory_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+ long ret = 0;
+
+ if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
+ return -EINVAL;
+ if (_IOC_NR(cmd) > _REMAP_PIN_MEM_AREA)
+ return -EINVAL;
+
+ switch (cmd) {
+ case SET_PIN_MEM_AREA:
+ ret = set_pin_mem_area(arg);
+ break;
+ case CLEAR_PIN_MEM_AREA:
+ clear_pin_memory_record();
+ break;
+ case REMAP_PIN_MEM_AREA:
+ ret = pin_mem_remap(arg);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static const struct file_operations pin_memory_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pin_memory_ioctl,
+ .compat_ioctl = pin_memory_ioctl,
+};
+
+static struct miscdevice pin_memory_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pinmem",
+ .fops = &pin_memory_fops,
+};
+
+static int pin_memory_init(void)
+{
+ int err = misc_register(&pin_memory_miscdev);
+ if (!err) {
+ pr_info("pin_memory init\n");
+ } else {
+ pr_warn("pin_memory init failed!\n");
+ }
+ return err;
+}
+
+static void pin_memory_exit(void)
+{
+ misc_deregister(&pin_memory_miscdev);
+ pr_info("pin_memory ko exists!\n");
+}
+
+module_init(pin_memory_init);
+module_exit(pin_memory_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Euler");
+MODULE_DESCRIPTION("pin memory");
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index 525510a..5baf40d 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -75,4 +75,9 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline, unsigned long long system_ram,
+ unsigned long long *pin_size, unsigned long long *pin_base);
+#endif
+
#endif /* LINUX_CRASH_CORE_H */
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
new file mode 100644
index 00000000..0ca44ac
--- /dev/null
+++ b/include/linux/pin_mem.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for check point and restore task.
+ */
+#ifndef _LINUX_PIN_MEMORY_H
+#define _LINUX_PIN_MEMORY_H
+
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/errno.h>
+#include <linux/kabi.h>
+#include <linux/mm_types.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARM64
+#include <linux/ioport.h>
+#endif
+
+#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)
+
+#define COLLECT_PAGES_FINISH 0
+#define COLLECT_PAGES_NEED_CONTINUE 1
+#define COLLECT_PAGES_FAIL -1
+
+#define COMPOUND_PAD_MASK 0xffffffff
+#define COMPOUND_PAD_START 0x88
+#define COMPOUND_PAD_DELTA 0x40
+#define LIST_POISON4 0xdead000000000400
+
+#define next_pme(pme) ((unsigned long *)(pme + 1) + pme->nr_pages)
+
+struct page_map_entry {
+ unsigned long virt_addr;
+ unsigned int nr_pages;
+ unsigned int is_huge_page;
+ unsigned long phy_addr_array[0];
+};
+
+struct page_map_info {
+ int pid;
+ int pid_reserved;
+ unsigned int entry_num;
+ struct page_map_entry *pme;
+};
+
+extern struct page_map_info *get_page_map_info(int pid);
+extern struct page_map_info *create_page_map_info(int pid);
+extern vm_fault_t do_mem_remap(int pid, struct mm_struct *mm);
+extern vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern void clear_pin_memory_record(void);
+extern int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr);
+extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+
+/* reserve space for pin memory*/
+#ifdef CONFIG_ARM64
+extern struct resource pin_memory_resource;
+#endif
+extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+
+#endif /* CONFIG_PIN_MEMORY */
+#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 9f1557b..7512696 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -292,6 +292,17 @@ int __init parse_crashkernel_low(char *cmdline,
"crashkernel=", suffix_tbl[SUFFIX_LOW]);
}
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *pin_size,
+ unsigned long long *pin_base)
+{
+ return __parse_crashkernel(cmdline, system_ram, pin_size, pin_base,
+ "pinmemory=", NULL);
+}
+#endif
+
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
void *data, size_t data_len)
{
diff --git a/mm/Kconfig b/mm/Kconfig
index ab80933..c2dd088 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -739,4 +739,10 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config PIN_MEMORY
+ bool "Support for pin memory"
+ depends on CHECKPOINT_RESTORE
+ help
+ Say y here to enable the pin memory feature for checkpoint
+ and restore.
endmenu
diff --git a/mm/Makefile b/mm/Makefile
index 1937cc2..7e1984e 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -108,3 +108,4 @@ obj-$(CONFIG_ZONE_DEVICE) += memremap.o
obj-$(CONFIG_HMM_MIRROR) += hmm.o
obj-$(CONFIG_MEMFD_CREATE) += memfd.o
obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
+obj-$(CONFIG_PIN_MEMORY) += pin_mem.o
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index a880932..93dc582 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3083,4 +3083,65 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
mlock_vma_page(new);
update_mmu_cache_pmd(vma, address, pvmw->pmd);
}
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ gfp_t gfp;
+ pgtable_t pgtable;
+ spinlock_t *ptl;
+ pmd_t entry;
+ vm_fault_t ret = 0;
+ struct mem_cgroup *memcg;
+
+ if (unlikely(anon_vma_prepare(vma)))
+ return VM_FAULT_OOM;
+ if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
+ return VM_FAULT_OOM;
+ gfp = alloc_hugepage_direct_gfpmask(vma);
+ prep_transhuge_page(page);
+ if (mem_cgroup_try_charge_delay(page, vma->vm_mm, gfp, &memcg, true)) {
+ put_page(page);
+ count_vm_event(THP_FAULT_FALLBACK);
+ return VM_FAULT_FALLBACK;
+ }
+ pgtable = pte_alloc_one(vma->vm_mm, address);
+ if (unlikely(!pgtable)) {
+ ret = VM_FAULT_OOM;
+ goto release;
+ }
+ __SetPageUptodate(page);
+ ptl = pmd_lock(vma->vm_mm, pmd);
+ if (unlikely(!pmd_none(*pmd))) {
+ goto unlock_release;
+ } else {
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto unlock_release;
+ entry = mk_huge_pmd(page, vma->vm_page_prot);
+ entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+ page_add_new_anon_rmap(page, vma, address, true);
+ mem_cgroup_commit_charge(page, memcg, false, true);
+ lru_cache_add_active_or_unevictable(page, vma);
+ pgtable_trans_huge_deposit(vma->vm_mm, pmd, pgtable);
+ set_pmd_at(vma->vm_mm, address, pmd, entry);
+ add_mm_counter(vma->vm_mm, MM_ANONPAGES, HPAGE_PMD_NR);
+ mm_inc_nr_ptes(vma->vm_mm);
+ spin_unlock(ptl);
+ count_vm_event(THP_FAULT_ALLOC);
+ }
+
+ return 0;
+unlock_release:
+ spin_unlock(ptl);
+release:
+ if (pgtable)
+ pte_free(vma->vm_mm, pgtable);
+ mem_cgroup_cancel_charge(page, memcg, true);
+ put_page(page);
+ return ret;
+}
+#endif
+
#endif
diff --git a/mm/memory.c b/mm/memory.c
index 45442d9..dd416fd 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4799,4 +4799,72 @@ void ptlock_free(struct page *page)
{
kmem_cache_free(page_ptl_cachep, page->ptl);
}
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ struct mem_cgroup *memcg;
+ pte_t entry;
+ spinlock_t *ptl;
+ pte_t *pte;
+ vm_fault_t ret = 0;
+
+ if (pte_alloc(vma->vm_mm, pmd, address))
+ return VM_FAULT_OOM;
+
+ /* See the comment in pte_alloc_one_map() */
+ if (unlikely(pmd_trans_unstable(pmd)))
+ return 0;
+
+ /* Allocate our own private page. */
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+
+ if (mem_cgroup_try_charge_delay(page, vma->vm_mm, GFP_KERNEL, &memcg,
+ false))
+ goto oom_free_page;
+
+ /*
+ * The memory barrier inside __SetPageUptodate makes sure that
+ * preceeding stores to the page contents become visible before
+ * the set_pte_at() write.
+ */
+ __SetPageUptodate(page);
+
+ entry = mk_pte(page, vma->vm_page_prot);
+ if (vma->vm_flags & VM_WRITE)
+ entry = pte_mkwrite(pte_mkdirty(entry));
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, address,
+ &ptl);
+ if (!pte_none(*pte)) {
+ ret = VM_FAULT_FALLBACK;
+ goto release;
+ }
+
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto release;
+ inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
+ page_add_new_anon_rmap(page, vma, address, false);
+ mem_cgroup_commit_charge(page, memcg, false, false);
+ lru_cache_add_active_or_unevictable(page, vma);
+
+ set_pte_at(vma->vm_mm, address, pte, entry);
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, pte);
+unlock:
+ pte_unmap_unlock(pte, ptl);
+ return ret;
+release:
+ mem_cgroup_cancel_charge(page, memcg, false);
+ put_page(page);
+ goto unlock;
+oom_free_page:
+ put_page(page);
+oom:
+ return VM_FAULT_OOM;
+}
+#endif
+
#endif
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
new file mode 100644
index 00000000..ca3f23a
--- /dev/null
+++ b/mm/pin_mem.c
@@ -0,0 +1,691 @@
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for check point and restore task.
+ */
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched/cputime.h>
+#include <linux/tick.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/pin_mem.h>
+#include <linux/idr.h>
+#include <linux/page-isolation.h>
+#include <linux/sched/mm.h>
+#include <linux/ctype.h>
+
+#define MAX_PIN_PID_NUM 128
+static DEFINE_SPINLOCK(page_map_entry_lock);
+
+unsigned int pin_pid_num;
+static unsigned int *pin_pid_num_addr;
+static unsigned long __page_map_entry_start;
+static unsigned long page_map_entry_end;
+static struct page_map_info *user_space_reserve_start;
+static struct page_map_entry *page_map_entry_start;
+unsigned int max_pin_pid_num __read_mostly;
+
+static int __init setup_max_pin_pid_num(char *str)
+{
+ int ret = 1;
+
+ if (!str)
+ goto out;
+
+ ret = kstrtouint(str, 10, &max_pin_pid_num);
+out:
+ if (ret) {
+ pr_warn("Unable to parse max pin pid num.\n");
+ } else {
+ if (max_pin_pid_num > MAX_PIN_PID_NUM) {
+ max_pin_pid_num = 0;
+ pr_warn("Input max_pin_pid_num is too large.\n");
+ }
+ }
+ return ret;
+}
+early_param("max_pin_pid_num", setup_max_pin_pid_num);
+
+struct page_map_info *create_page_map_info(int pid)
+{
+ struct page_map_info *new;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ if (pin_pid_num >= max_pin_pid_num) {
+ pr_warn("Pin pid num too large than max_pin_pid_num, fail create: %d!", pid);
+ return NULL;
+ }
+ new = (struct page_map_info *)(user_space_reserve_start + pin_pid_num);
+ new->pid = pid;
+ new->pme = NULL;
+ new->entry_num = 0;
+ new->pid_reserved = false;
+ (*pin_pid_num_addr)++;
+ pin_pid_num++;
+ return new;
+}
+EXPORT_SYMBOL_GPL(create_page_map_info);
+
+struct page_map_info *get_page_map_info(int pid)
+{
+ int i;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ for (i = 0; i < pin_pid_num; i++) {
+ if (user_space_reserve_start[i].pid == pid) {
+ return &(user_space_reserve_start[i]);
+ }
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(get_page_map_info);
+
+static struct page *find_head_page(struct page *page)
+{
+ struct page *p = page;
+
+ while (!PageBuddy(p)) {
+ if (PageLRU(p))
+ return NULL;
+ p--;
+ }
+ return p;
+}
+
+static void spilt_page_area_left(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ unsigned long total_size = 0;
+ struct page *tmp;
+ unsigned long tmp_size = size;
+
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ list_add(&page[total_size].lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(page[total_size]._mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(&page[total_size], order);
+ set_pageblock_migratetype(&page[total_size], MIGRATE_MOVABLE);
+ area->nr_free++;
+ total_size += cur_size;
+ size -= cur_size;
+ }
+ }
+}
+
+static void spilt_page_area_right(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ struct page *right_page, *head_page;
+ unsigned long tmp_size = size;
+
+ right_page = page + size;
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ head_page = right_page - cur_size;
+ list_add(&head_page->lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(head_page->_mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(head_page, order);
+ set_pageblock_migratetype(head_page, MIGRATE_MOVABLE);
+ area->nr_free++;
+ size -= cur_size;
+ right_page = head_page;
+ }
+ }
+}
+
+void reserve_page_from_buddy(unsigned long nr_pages, struct page *page)
+{
+ unsigned int current_order;
+ struct page *page_end;
+ struct free_area *area;
+ struct zone *zone;
+ struct page *head_page;
+
+ head_page = find_head_page(page);
+ if (!head_page) {
+ pr_warn("Find page head fail.");
+ return;
+ }
+ current_order = head_page->private;
+ page_end = head_page + (1 << current_order);
+ zone = page_zone(head_page);
+ area = &(zone->free_area[current_order]);
+ list_del(&head_page->lru);
+ atomic_set(&head_page->_mapcount, -1);
+ set_page_private(head_page, 0);
+ area->nr_free--;
+ if (head_page != page)
+ spilt_page_area_left(zone, area, head_page,
+ (unsigned long)(page - head_page), current_order);
+ page = page + nr_pages;
+ if (page < page_end) {
+ spilt_page_area_right(zone, area, page,
+ (unsigned long)(page_end - page), current_order);
+ } else if (page > page_end) {
+ pr_warn("Find page end smaller than page.");
+ }
+}
+
+static inline void reserve_user_normal_pages(struct page *page)
+{
+ if (!atomic_read(&page->_refcount)) {
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy(1, page);
+ } else {
+ pr_warn("Page %pK refcount %d large than zero, no need reserve.\n",
+ page, page->_refcount.counter);
+ }
+}
+
+static void init_huge_pmd_pages(struct page *head_page)
+{
+ int i = 0;
+ struct page *page = head_page;
+ unsigned long *temp;
+ unsigned long compound_pad = COMPOUND_PAD_START;
+
+ __set_bit(PG_head, &page->flags);
+ __set_bit(PG_active, &page->flags);
+ atomic_set(&page->_refcount, 1);
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ page->_compound_pad_2 = (unsigned long)head_page & COMPOUND_PAD_MASK;
+ temp = (unsigned long *)(&(page->_compound_pad_2));
+ temp[1] = LIST_POISON4;
+ page->compound_dtor = HUGETLB_PAGE_DTOR + 1;
+ page->compound_order = HPAGE_PMD_ORDER;
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ page->_compound_pad_2 = (unsigned long)head_page + compound_pad;
+ i++;
+ INIT_LIST_HEAD(&(page->deferred_list));
+ for (; i < HPAGE_PMD_NR; i++) {
+ page = head_page + i;
+ page->compound_head = (unsigned long)head_page + 1;
+ compound_pad += COMPOUND_PAD_DELTA;
+ page->_compound_pad_2 = (unsigned long)head_page + compound_pad;
+ temp = (unsigned long *)(&(page->_compound_pad_2));
+ temp[1] = LIST_POISON4;
+ }
+}
+
+static void reserve_user_huge_pmd_pages(struct page *page)
+{
+ struct page *head_page;
+
+ if (!atomic_read(&page->_refcount)) {
+ atomic_inc(&page->_refcount);
+ head_page = find_head_page(page);
+ reserve_page_from_buddy((1 << HPAGE_PMD_ORDER), page);
+ init_huge_pmd_pages(page);
+ } else {
+ pr_warn("Page %pK refcount %d large than zero, no need reserve.\n",
+ page, page->_refcount.counter);
+ }
+}
+
+static void reserve_user_space_map_pages(void)
+{
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned int i, j, index;
+ struct page *page;
+ unsigned long flags;
+ unsigned long page_size;
+ int err = 0;
+ unsigned long phy_addr;
+
+ if (!user_space_reserve_start)
+ return;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+
+ for (i = 0; i < pmi->entry_num; i++) {
+ err = 0;
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (atomic_read(&page->_refcount)) {
+ pme->phy_addr_array[j] = 0;
+ page_size = pme->is_huge_page ? HPAGE_PMD_SIZE : PAGE_SIZE;
+ continue;
+ }
+ if (!pme->is_huge_page) {
+ reserve_user_normal_pages(page);
+ } else {
+ reserve_user_huge_pmd_pages(page);
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ if (err)
+ err_phy_num++;
+ }
+ page_size = pme->is_huge_page ? HPAGE_PMD_SIZE : PAGE_SIZE;
+ }
+ spin_unlock(&page_map_entry_lock);
+}
+
+
+/* The whole page map entry collect process must be Sequentially.
+ The user_space_reserve_start points to the first page map info for
+ the first dump task. And the page_map_entry_start points to
+ the first page map entry of the first dump vma. */
+static void init_page_map_info(unsigned int *map_addr)
+{
+ unsigned long map_len = pin_memory_resource.end - pin_memory_resource.start;
+
+ if (user_space_reserve_start || !max_pin_pid_num)
+ return;
+ pin_pid_num = *map_addr;
+ pin_pid_num_addr = map_addr;
+ user_space_reserve_start =
+ (struct kup_page_map_info *)(map_addr + 1);
+ page_map_entry_start =
+ (struct page_map_entry *)(user_space_reserve_start + max_pin_pid_num);
+ page_map_entry_end = (unsigned long)map_addr + map_len;
+ if (pin_pid_num > 0)
+ reserve_user_space_map_pages();
+}
+
+int collect_pmd_huge_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ long res;
+ int index = 0;
+ unsigned long start = start_addr;
+ struct page *temp_page;
+
+ while (start < end_addr) {
+ temp_page = NULL;
+ res = get_user_pages_remote(task, task->mm, start, 1,
+ FOLL_TOUCH|FOLL_GET, &temp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get huge page for addr(%lx) fail.", start);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(temp_page)) {
+ start += HPAGE_PMD_SIZE;
+ pme->phy_addr_array[index] = page_to_phys(temp_page);
+ index++;
+ } else {
+ pme->nr_pages = index;
+ atomic_dec(&((temp_page)->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ }
+ pme->nr_pages = index;
+ return COLLECT_PAGES_FINISH;
+}
+
+int collect_normal_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ int res;
+ unsigned long next;
+ unsigned long i, nr_pages;
+ struct page *tmp_page;
+ unsigned long *phy_addr_array = pme->phy_addr_array;
+ struct page **page_array = (struct page **)pme->phy_addr_array;
+
+ next = (start_addr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
+ next = (next > end_addr) ? end_addr : next;
+ pme->nr_pages = 0;
+ while (start_addr < next) {
+ nr_pages = (next - start_addr) / PAGE_SIZE;
+ res = get_user_pages_remote(task, task->mm, start_addr, 1,
+ FOLL_TOUCH|FOLL_GET, &tmp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user pages of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(tmp_page)) {
+ atomic_dec(&(tmp_page->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ atomic_dec(&(tmp_page->_refcount));
+ if (PageTail(tmp_page)) {
+ start_addr = next;
+ pme->virt_addr = start_addr;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ? end_addr : (next + HPAGE_PMD_SIZE);
+ continue;
+ }
+ res = get_user_pages_remote(task, task->mm, start_addr, nr_pages,
+ FOLL_TOUCH|FOLL_GET, page_array, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user pages of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ for (i = 0; i < nr_pages; i++) {
+ phy_addr_array[i] = page_to_phys(page_array[i]);
+ }
+ pme->nr_pages += nr_pages;
+ page_array += nr_pages;
+ phy_addr_array += nr_pages;
+ start_addr = next;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ? end_addr : (next + HPAGE_PMD_SIZE);
+ }
+ return COLLECT_PAGES_FINISH;
+}
+
+/* Users make sure that the pin memory belongs to anonymous vma. */
+int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr)
+{
+ int pid, ret;
+ int is_huge_page = false;
+ unsigned int page_size;
+ unsigned long nr_pages, flags;
+ struct page_map_entry *pme;
+ struct page_map_info *pmi;
+ struct vm_area_struct *vma;
+ unsigned long i;
+ struct page *tmp_page;
+
+ if (!page_map_entry_start
+ || !task || !mm
+ || start_addr >= end_addr)
+ return -EFAULT;
+
+ pid = task->pid;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ nr_pages = ((end_addr - start_addr) / PAGE_SIZE);
+ if ((unsigned long)page_map_entry_start + nr_pages * sizeof(struct page *)
+ >= page_map_entry_end) {
+ pr_warn("Page map entry use up!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ vma = find_extend_vma(mm, start_addr);
+ if (!vma) {
+ pr_warn("Find no match vma!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (start_addr == (start_addr & HPAGE_PMD_MASK) &&
+ transparent_hugepage_enabled(vma)) {
+ page_size = HPAGE_PMD_SIZE;
+ is_huge_page = true;
+ } else {
+ page_size = PAGE_SIZE;
+ }
+ pme = page_map_entry_start;
+ pme->virt_addr = start_addr;
+ pme->is_huge_page = is_huge_page;
+ memset(pme->phy_addr_array, 0, nr_pages * sizeof(unsigned long));
+ down_write(&mm->mmap_sem);
+ if (!is_huge_page) {
+ ret = collect_normal_pages(task, start_addr, end_addr, pme);
+ if (!pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_sem);
+ goto finish;
+ }
+ pme->is_huge_page = true;
+ page_size = HPAGE_PMD_SIZE;
+ ret = collect_pmd_huge_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ } else {
+ ret = collect_pmd_huge_pages(task, start_addr, end_addr, pme);
+ if (!pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_sem);
+ goto finish;
+ }
+ pme->is_huge_page = false;
+ page_size = PAGE_SIZE;
+ ret = collect_normal_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ }
+ up_write(&mm->mmap_sem);
+ if (ret == COLLECT_PAGES_FAIL) {
+ ret = -EFAULT;
+ goto finish;
+ }
+
+ /* check for zero pages */
+ for (i = 0; i < pme->nr_pages; i++) {
+ tmp_page = phys_to_page(pme->phy_addr_array[i]);
+ if (!pme->is_huge_page) {
+ if (page_to_pfn(tmp_page) == my_zero_pfn(pme->virt_addr + i * PAGE_SIZE))
+ pme->phy_addr_array[i] = 0;
+ } else if (is_huge_zero_page(tmp_page))
+ pme->phy_addr_array[i] = 0;
+ }
+
+ page_map_entry_start = (struct page_map_entry *)(next_pme(pme));
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ pmi = create_page_map_info(pid);
+ if (!pmi) {
+ pr_warn("Create page map info fail for pid: %d!\n", pid);
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (!pmi->pme)
+ pmi->pme = pme;
+ pmi->entry_num++;
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ if (ret == COLLECT_PAGES_NEED_CONTINUE) {
+ ret = pin_mem_area(task, mm, pme->virt_addr + pme->nr_pages * page_size, end_addr);
+ }
+ return ret;
+finish:
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pin_mem_area);
+
+vm_fault_t remap_normal_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ struct page *page;
+ unsigned long address;
+ unsigned long phy_addr;
+
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * PAGE_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (page->flags & (1 << PG_reserved))
+ page->flags -= (1 << PG_reserved);
+ if (page_to_pfn(page) == my_zero_pfn(address)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ page->mapping = NULL;
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d)
+ return VM_FAULT_OOM;
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud)
+ return VM_FAULT_OOM;
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd)
+ return VM_FAULT_OOM;
+ ret = do_anon_page_remap(vma, address, pmd, page);
+ if (ret == VM_FAULT_OOM)
+ return ret;
+ }
+ return 0;
+}
+
+vm_fault_t remap_huge_pmd_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ struct page *page;
+ unsigned long address;
+ unsigned long phy_addr;
+
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * HPAGE_PMD_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (page->flags & (1 << PG_reserved))
+ page->flags -= (1 << PG_reserved);
+ if (is_huge_zero_page(page)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d)
+ return VM_FAULT_OOM;
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud)
+ return VM_FAULT_OOM;
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd)
+ return VM_FAULT_OOM;
+ ret = do_anon_huge_page_remap(vma, address, pmd, page);
+ if (ret == VM_FAULT_OOM)
+ return ret;
+ }
+ return 0;
+}
+
+vm_fault_t do_mem_remap(int pid, struct mm_struct *mm)
+{
+ unsigned int i = 0;
+ vm_fault_t ret = 0;
+ struct vm_area_struct *vma;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ return -EFAULT;
+ down_write(&mm->mmap_sem);
+ pme = pmi->pme;
+ vma = mm->mmap;
+ while ((i < pmi->entry_num) && (vma != NULL)) {
+ if (pme->virt_addr >= vma->vm_start && pme->virt_addr < vma->vm_end) {
+ i++;
+ if (!vma_is_anonymous(vma)) {
+ pme = (struct page_map_entry *)(next_pme(pme));
+ continue;
+ }
+ if (!pme->is_huge_page) {
+ ret = remap_normal_pages(mm, vma, pme);
+ if (ret < 0)
+ goto out;
+ } else {
+ ret = remap_huge_pmd_pages(mm, vma, pme);
+ if (ret < 0)
+ goto out;
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ } else {
+ vma = vma->vm_next;
+ }
+ }
+out:
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(do_mem_remap);
+
+#if defined(CONFIG_ARM64)
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+ void *addr;
+
+ if (!map_addr || !map_size)
+ return;
+ addr = phys_to_virt(map_addr);
+ init_page_map_info((unsigned int *)addr);
+}
+#else
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+}
+#endif
+
+/* Clear all pin memory record. */
+void clear_pin_memory_record(void)
+{
+ if (pin_pid_num_addr) {
+ *pin_pid_num_addr = 0;
+ pin_pid_num = 0;
+ page_map_entry_start = (struct page_map_entry *)__page_map_entry_start;
+ }
+ if (kernel_space_reserve_start && kernel_pin_space_size > 0) {
+ *(unsigned long *)kernel_space_reserve_start = 0;
+ }
+}
+EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+
+vm_fault_t reserve_kernel_space_mem(unsigned long start_addr, unsigned int pages)
+{
+ unsigned long i;
+ unsigned long entry_num;
+ struct page_map_entry *pme, *pme_start;
+
+
+ entry_num = *(unsigned long *)kernel_space_reserve_start;
+ pme_start = (struct page_map_entry *)(kernel_space_reserve_start + sizeof(entry_num));
+ pme = pme_start;
+ spin_lock(&page_map_entry_lock);
+ for (i = 0; i < entry_num; i++) {
+ if (start_addr == pme->virt_addr) {
+ spin_unlock(&page_map_entry_lock);
+ return 0;
+ }
+ pme = pme + 1;
+ }
+ if ((unsigned long)(pme_start + entry_num) >= kernel_space_reserve_end) {
+ spin_unlock(&page_map_entry_lock);
+ return VM_FAULT_OOM;
+ }
+ pme = pme_start + entry_num;
+ pme->virt_addr = start_addr;
+ pme->nr_pages = pages;
+ pme->is_huge_page = false;
+ *(unsigned long *)kernel_space_reserve_start = entry_num + 1;
+ spin_unlock(&page_map_entry_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(reserve_kernel_space_mem);
+
+#endif /* CONFIG_PIN_MEMORY */
--
1.8.3.1
1
0
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
MAP_PA32BIT was defined in uapi/asm-generic/mman.h, that was not
automatically included by mm/mmap.c when building on mips platform, and
result in following compiling error:
mm/mmap.c: In function ‘do_mmap’:
mm/mmap.c:1450:14: error: ‘MAP_PA32BIT’ undeclared (first use in this function); did you mean ‘MAP_32BIT’?
if (flags & MAP_PA32BIT)
^~~~~~~~~~~
MAP_32BIT
mm/mmap.c:1450:14: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [scripts/Makefile.build:303: mm/mmap.o] Error 1
Fixes: e138253f2b82 ("svm: add support for allocing memory which is within 4G physical address in svm_mmap")
Signed-off-by: Zhengyuan Liu <liuzhengyuan(a)tj.kylinos.cn>
---
arch/mips/include/uapi/asm/mman.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 3035ca499cd8..0247a3c705af 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -51,6 +51,7 @@
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+#define MAP_PA32BIT 0x400000
/*
* Flags for msync
--
2.17.1
4
4
*** BLURB HERE ***
Alexey Kardashevskiy (1):
serial_core: Check for port state when tty is in error state
Anant Thazhemadam (2):
fs: quota: fix array-index-out-of-bounds bug by passing correct
argument to vfs_cleanup_quota_inode()
nl80211: validate key indexes for cfg80211_registered_device
Andi Kleen (1):
x86/split-lock: Avoid returning with interrupts enabled
Antti Palosaari (1):
media: msi2500: assign SPI bus number dynamically
Arnd Bergmann (1):
scsi: megaraid_sas: Check user-provided offsets
Artem Labazov (1):
exfat: Avoid allocating upcase table using kcalloc()
Chao Yu (1):
f2fs: fix to seek incorrect data offset in inline data file
Dae R. Jeong (1):
md: fix a warning caused by a race between concurrent md_ioctl()s
Dan Carpenter (1):
usb: mtu3: fix memory corruption in mtu3_debugfs_regset()
Eric Biggers (6):
fscrypt: remove kernel-internal constants from UAPI header
fscrypt: add fscrypt_is_nokey_name()
ubifs: prevent creating duplicate encrypted filenames
ext4: prevent creating duplicate encrypted filenames
f2fs: prevent creating duplicate encrypted filenames
crypto: af_alg - avoid undefined behavior accessing salg_name
Fabio Estevam (1):
usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to
imx6ul
Jack Pham (1):
usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
Jack Qiu (1):
f2fs: init dirty_secmap incorrectly
Jan Kara (1):
quota: Sanity-check quota file headers on load
Johan Hovold (1):
USB: serial: option: add interface-number sanity check to flag
handling
Julian Sax (1):
HID: i2c-hid: add Vero K147 to descriptor override
Krzysztof Kozlowski (3):
ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on
Exynos5410
ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid
XU
Mao Jinlong (1):
coresight: tmc-etr: Check if page is valid before dma_map_page()
Nicolin Chen (1):
soc/tegra: fuse: Fix index bug in get_process_id
Peilin Ye (1):
Bluetooth: Fix slab-out-of-bounds read in
hci_le_direct_adv_report_evt()
Sai Prakash Ranjan (3):
coresight: tmc-etf: Fix NULL ptr dereference in
tmc_enable_etf_sink_perf()
coresight: etb10: Fix possible NULL ptr dereference in
etb_enable_perf()
coresight: etm4x: Skip setting LPOVERRIDE bit for qcom, skip-power-up
Suzuki K Poulose (5):
coresight: tmc-etr: Fix barrier packet insertion for perf buffer
coresight: etm4x: Fix accesses to TRCVMIDCTLR1
coresight: etm4x: Fix accesses to TRCCIDCTLR1
coresight: etm4x: Fix accesses to TRCPROCSELR
coresight: etm4x: Handle TRCVIPCSSCTLR accesses
Thierry Reding (1):
net: ipconfig: Avoid spurious blank lines in boot log
Will McVicker (2):
USB: gadget: f_midi: setup SuperSpeed Plus descriptors
USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
taehyun.cho (1):
USB: gadget: f_acm: add support for SuperSpeed Plus
arch/arm/boot/dts/exynos5410-odroidxu.dts | 6 ++-
arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 28 ++++++++++
arch/arm/boot/dts/exynos5410.dtsi | 4 ++
arch/x86/kernel/traps.c | 3 +-
crypto/af_alg.c | 10 ++--
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c | 8 +++
drivers/hwtracing/coresight/coresight-etb10.c | 4 +-
.../coresight/coresight-etm4x-core.c | 41 +++++++++------
drivers/hwtracing/coresight/coresight-priv.h | 2 +
.../hwtracing/coresight/coresight-tmc-etf.c | 4 +-
.../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
drivers/md/md.c | 7 ++-
drivers/media/usb/msi2500/msi2500.c | 2 +-
drivers/scsi/megaraid/megaraid_sas_base.c | 16 ++++--
drivers/soc/tegra/fuse/speedo-tegra210.c | 2 +-
drivers/tty/serial/serial_core.c | 4 ++
drivers/usb/chipidea/ci_hdrc_imx.c | 3 +-
drivers/usb/gadget/function/f_acm.c | 2 +-
drivers/usb/gadget/function/f_fs.c | 5 +-
drivers/usb/gadget/function/f_midi.c | 6 +++
drivers/usb/gadget/function/f_rndis.c | 4 +-
drivers/usb/mtu3/mtu3_debugfs.c | 2 +-
drivers/usb/serial/option.c | 23 ++++++++-
fs/crypto/fscrypt_private.h | 9 ++--
fs/crypto/hooks.c | 5 +-
fs/crypto/keyring.c | 2 +-
fs/crypto/keysetup.c | 4 +-
fs/crypto/policy.c | 5 +-
fs/exfat/nls.c | 6 +--
fs/ext4/namei.c | 3 ++
fs/f2fs/f2fs.h | 2 +
fs/f2fs/file.c | 11 ++--
fs/f2fs/segment.c | 2 +-
fs/quota/dquot.c | 2 +-
fs/quota/quota_v2.c | 19 +++++++
fs/ubifs/dir.c | 17 +++++--
include/linux/fscrypt.h | 34 +++++++++++++
include/uapi/linux/fscrypt.h | 5 +-
include/uapi/linux/if_alg.h | 16 ++++++
net/bluetooth/hci_event.c | 12 ++---
net/ipv4/ipconfig.c | 14 +++--
net/wireless/core.h | 2 +
net/wireless/nl80211.c | 7 +--
net/wireless/util.c | 51 ++++++++++++++++---
44 files changed, 332 insertions(+), 86 deletions(-)
--
2.25.0
2
41
Some bugfix patches for kdump.
Hanjun Guo (1):
arm64: smp: wait 50 seconds for other CPUs to stop for kexec
Yingliang Yang (1):
arm64: kdump: fix timer interrupts panic, could not boot
capture_kernel
arch/arm64/kernel/machine_kexec.c | 16 ++++++++++++++++
arch/arm64/kernel/smp.c | 4 ++--
2 files changed, 18 insertions(+), 2 deletions(-)
--
2.20.1
2
3
29 Dec '20
From: chenjiajun <chenjiajun8(a)huawei.com>
virt inclusion
category: feature
bugzilla: 46853
CVE: NA
Export kvm vcpu info in debugfs entry /sys/kernel/debug/kvm/vcpu_stat,
this entry contains kvm exits and cputime items now. And then, we can get all
kvm vcpu info through this debugfs instead of one entry per kvm exits
items, which will greatly facilitates the collection of performance status.
Currently, only support x86 and aarch64.
--
ChangeList:
v3:
modify kzfree in patches
v2:
modify architecture-dependent st_max to avoid compile err in other arches
v1:
kvm: debugfs: support vcpu_stat debugfs
chenjiajun (4):
kvm: debugfs: Export vcpu stat via debugfs
kvm: debugfs: export remaining aarch64 kvm exit reasons to debugfs
kvm: debugfs: aarch64 export cpu time related items to debugfs
kvm: debugfs: Export x86 kvm exits to vcpu_stat
arch/arm64/include/asm/kvm_host.h | 21 ++++
arch/arm64/kvm/arm.c | 23 +++++
arch/arm64/kvm/guest.c | 33 +++++++
arch/arm64/kvm/handle_exit.c | 8 ++
arch/arm64/kvm/hyp/include/hyp/switch.h | 1 +
arch/arm64/kvm/mmu.c | 1 +
arch/arm64/kvm/sys_regs.c | 11 +++
arch/x86/include/asm/kvm_host.h | 13 +++
arch/x86/kvm/vmx/vmx.c | 10 ++
arch/x86/kvm/x86.c | 70 +++++++++++++
include/linux/kvm_host.h | 19 ++++
virt/kvm/kvm_main.c | 125 ++++++++++++++++++++++++
12 files changed, 335 insertions(+)
--
2.29.GIT
3
6
*** BLURB HERE ***
Alexey Kardashevskiy (1):
serial_core: Check for port state when tty is in error state
Anant Thazhemadam (2):
fs: quota: fix array-index-out-of-bounds bug by passing correct
argument to vfs_cleanup_quota_inode()
nl80211: validate key indexes for cfg80211_registered_device
Andi Kleen (1):
x86/split-lock: Avoid returning with interrupts enabled
Antti Palosaari (1):
media: msi2500: assign SPI bus number dynamically
Arnd Bergmann (1):
scsi: megaraid_sas: Check user-provided offsets
Artem Labazov (1):
exfat: Avoid allocating upcase table using kcalloc()
Chao Yu (1):
f2fs: fix to seek incorrect data offset in inline data file
Dae R. Jeong (1):
md: fix a warning caused by a race between concurrent md_ioctl()s
Dan Carpenter (1):
usb: mtu3: fix memory corruption in mtu3_debugfs_regset()
Eric Biggers (6):
fscrypt: remove kernel-internal constants from UAPI header
fscrypt: add fscrypt_is_nokey_name()
ubifs: prevent creating duplicate encrypted filenames
ext4: prevent creating duplicate encrypted filenames
f2fs: prevent creating duplicate encrypted filenames
crypto: af_alg - avoid undefined behavior accessing salg_name
Fabio Estevam (1):
usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to
imx6ul
Jack Pham (1):
usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
Jack Qiu (1):
f2fs: init dirty_secmap incorrectly
Jan Kara (1):
quota: Sanity-check quota file headers on load
Johan Hovold (1):
USB: serial: option: add interface-number sanity check to flag
handling
Julian Sax (1):
HID: i2c-hid: add Vero K147 to descriptor override
Krzysztof Kozlowski (3):
ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on
Exynos5410
ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid
XU
Mao Jinlong (1):
coresight: tmc-etr: Check if page is valid before dma_map_page()
Nicolin Chen (1):
soc/tegra: fuse: Fix index bug in get_process_id
Peilin Ye (1):
Bluetooth: Fix slab-out-of-bounds read in
hci_le_direct_adv_report_evt()
Sai Prakash Ranjan (3):
coresight: tmc-etf: Fix NULL ptr dereference in
tmc_enable_etf_sink_perf()
coresight: etb10: Fix possible NULL ptr dereference in
etb_enable_perf()
coresight: etm4x: Skip setting LPOVERRIDE bit for qcom, skip-power-up
Suzuki K Poulose (5):
coresight: tmc-etr: Fix barrier packet insertion for perf buffer
coresight: etm4x: Fix accesses to TRCVMIDCTLR1
coresight: etm4x: Fix accesses to TRCCIDCTLR1
coresight: etm4x: Fix accesses to TRCPROCSELR
coresight: etm4x: Handle TRCVIPCSSCTLR accesses
Thierry Reding (1):
net: ipconfig: Avoid spurious blank lines in boot log
Will McVicker (2):
USB: gadget: f_midi: setup SuperSpeed Plus descriptors
USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
taehyun.cho (1):
USB: gadget: f_acm: add support for SuperSpeed Plus
arch/arm/boot/dts/exynos5410-odroidxu.dts | 6 ++-
arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 28 ++++++++++
arch/arm/boot/dts/exynos5410.dtsi | 4 ++
arch/x86/kernel/traps.c | 3 +-
crypto/af_alg.c | 10 ++--
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c | 8 +++
drivers/hwtracing/coresight/coresight-etb10.c | 4 +-
.../coresight/coresight-etm4x-core.c | 41 +++++++++------
drivers/hwtracing/coresight/coresight-priv.h | 2 +
.../hwtracing/coresight/coresight-tmc-etf.c | 4 +-
.../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
drivers/md/md.c | 7 ++-
drivers/media/usb/msi2500/msi2500.c | 2 +-
drivers/scsi/megaraid/megaraid_sas_base.c | 16 ++++--
drivers/soc/tegra/fuse/speedo-tegra210.c | 2 +-
drivers/tty/serial/serial_core.c | 4 ++
drivers/usb/chipidea/ci_hdrc_imx.c | 3 +-
drivers/usb/gadget/function/f_acm.c | 2 +-
drivers/usb/gadget/function/f_fs.c | 5 +-
drivers/usb/gadget/function/f_midi.c | 6 +++
drivers/usb/gadget/function/f_rndis.c | 4 +-
drivers/usb/mtu3/mtu3_debugfs.c | 2 +-
drivers/usb/serial/option.c | 23 ++++++++-
fs/crypto/fscrypt_private.h | 9 ++--
fs/crypto/hooks.c | 5 +-
fs/crypto/keyring.c | 2 +-
fs/crypto/keysetup.c | 4 +-
fs/crypto/policy.c | 5 +-
fs/exfat/nls.c | 6 +--
fs/ext4/namei.c | 3 ++
fs/f2fs/f2fs.h | 2 +
fs/f2fs/file.c | 11 ++--
fs/f2fs/segment.c | 2 +-
fs/quota/dquot.c | 2 +-
fs/quota/quota_v2.c | 19 +++++++
fs/ubifs/dir.c | 17 +++++--
include/linux/fscrypt.h | 34 +++++++++++++
include/uapi/linux/fscrypt.h | 5 +-
include/uapi/linux/if_alg.h | 16 ++++++
net/bluetooth/hci_event.c | 12 ++---
net/ipv4/ipconfig.c | 14 +++--
net/wireless/core.h | 2 +
net/wireless/nl80211.c | 7 +--
net/wireless/util.c | 51 ++++++++++++++++---
44 files changed, 332 insertions(+), 86 deletions(-)
--
2.25.0
2
22
some bugfix patches for kdump.
Hanjun Guo (1):
[Huawei] arm64: smp: wait 50 seconds for other CPUs to stop for kexec
Yingliang Yang (1):
[Huawei] arm64: kdump: fix timer interrupts panic, could not boot
capture_kernel
arch/arm64/kernel/machine_kexec.c | 16 ++++++++++++++++
arch/arm64/kernel/smp.c | 4 ++--
2 files changed, 18 insertions(+), 2 deletions(-)
--
2.20.1
1
2
[PATCH kernel-4.19 1/4] modpost: add read_text_file() and get_line() helpers
by Yang Yingliang 28 Dec '20
by Yang Yingliang 28 Dec '20
28 Dec '20
From: Masahiro Yamada <masahiroy(a)kernel.org>
mainline inclusion
from mainline-5.8
commit ac5100f54329676469688d1b5415cd8d6428c909
category: bugfix
bugzilla: 46847
CVE: NA
-----------------------------------------------
modpost uses grab_file() to open a file, but it is not suitable for
a text file because the mmap'ed file is not terminated by null byte.
Actually, I see some issues for the use of grab_file().
The new helper, read_text_file() loads the whole file content into a
malloc'ed buffer, and appends a null byte. Then, get_line() reads
each line.
To handle text files, I intend to replace as follows:
grab_file() -> read_text_file()
get_new_line() -> get_line()
Signed-off-by: Masahiro Yamada <masahiroy(a)kernel.org>
Signed-off-by: Wang Wensheng <wangwensheng4(a)huawei.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
scripts/mod/modpost.c | 49 +++++++++++++++++++++++++++++++++++++++++++
scripts/mod/modpost.h | 2 ++
2 files changed, 51 insertions(+)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 91a80036c05d..99334521909b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -118,6 +118,55 @@ void *do_nofail(void *ptr, const char *expr)
return ptr;
}
+char *read_text_file(const char *filename)
+{
+ struct stat st;
+ size_t nbytes;
+ int fd;
+ char *buf;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ if (fstat(fd, &st) < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ buf = NOFAIL(malloc(st.st_size + 1));
+
+ nbytes = st.st_size;
+
+ while (nbytes) {
+ ssize_t bytes_read;
+
+ bytes_read = read(fd, buf, nbytes);
+ if (bytes_read < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ nbytes -= bytes_read;
+ }
+ buf[st.st_size] = '\0';
+
+ close(fd);
+
+ return buf;
+}
+
+char *get_line(char **stringp)
+{
+ /* do not return the unwanted extra line at EOF */
+ if (*stringp && **stringp == '\0')
+ return NULL;
+
+ return strsep(stringp, "\n");
+}
+
/* A list of all modules we processed */
static struct module *modules;
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 8453d6ac2f77..ff809119f82b 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -185,6 +185,8 @@ void maybe_frob_rcs_version(const char *modfilename,
void get_src_version(const char *modname, char sum[], unsigned sumlen);
/* from modpost.c */
+char *read_text_file(const char *filename);
+char *get_line(char **stringp);
void *grab_file(const char *filename, unsigned long *size);
char* get_next_line(unsigned long *pos, void *file, unsigned long size);
void release_file(void *file, unsigned long size);
--
2.25.1
1
3
*** BLURB HERE ***
yu kuai (6):
fs/dirty_pages: dump the number of dirty pages for each inode
fs/dirty_pages: fix index out of bounds and integer overflow
fs/dirty_pages: fix wrong 'buff_num' after invalid input
fs/dirty_pages: Adjust position of some code to improve the code
fs/dirty_pages: fix kernel panic in concurrency mode
fs/dirty_pages: remove set but not used variable 'm'
fs/Makefile | 1 +
fs/dirty_pages.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 467 insertions(+)
create mode 100644 fs/dirty_pages.c
--
2.25.0
2
7
*** BLURB HERE ***
Alan Stern (1):
USB: legotower: fix logical error in recent commit
Alexander Sverdlin (1):
serial: 8250_omap: Avoid FIFO corruption caused by MDR1 access
Bui Quang Minh (1):
USB: dummy-hcd: Fix uninitialized array use in init()
Hans de Goede (1):
xhci-pci: Allow host runtime PM as default for Intel Alpine Ridge LP
Li Jun (1):
xhci: Give USB2 ports time to enter U3 in bus suspend
Mika Westerberg (1):
xhci-pci: Allow host runtime PM as default for Intel Maple Ridge xHCI
Oliver Neukum (2):
USB: add RESET_RESUME quirk for Snapscan 1212
USB: UAS: introduce a quirk to set no_write_same
Peilin Ye (1):
ptrace: Prevent kernel-infoleak in ptrace_get_syscall_info()
Steven Rostedt (VMware) (2):
ktest.pl: If size of log is too big to email, email error message
ktest.pl: Fix the logic for truncating the size of the log file for
email
Takashi Iwai (3):
ALSA: usb-audio: Fix potential out-of-bounds shift
ALSA: usb-audio: Fix control 'access overflow' errors from chmap
ALSA: pcm: oss: Fix potential out-of-bounds shift
Tejas Joglekar (1):
usb: xhci: Set quirk for XHCI_SG_TRB_CACHE_SIZE_QUIRK
Thomas Gleixner (1):
USB: sisusbvga: Make console support depend on BROKEN
.../admin-guide/kernel-parameters.txt | 1 +
drivers/tty/serial/8250/8250_omap.c | 5 -----
drivers/usb/core/quirks.c | 3 +++
drivers/usb/gadget/udc/dummy_hcd.c | 2 +-
drivers/usb/host/xhci-hub.c | 4 ++++
drivers/usb/host/xhci-pci.c | 6 +++++-
drivers/usb/host/xhci-plat.c | 3 +++
drivers/usb/host/xhci.h | 1 +
drivers/usb/misc/legousbtower.c | 2 +-
drivers/usb/misc/sisusbvga/Kconfig | 2 +-
drivers/usb/storage/uas.c | 3 +++
drivers/usb/storage/unusual_uas.h | 7 +++++--
drivers/usb/storage/usb.c | 3 +++
include/linux/usb_usual.h | 2 ++
include/uapi/linux/ptrace.h | 3 ++-
sound/core/oss/pcm_oss.c | 6 +++++-
sound/usb/format.c | 2 ++
sound/usb/stream.c | 6 +++---
tools/testing/ktest/ktest.pl | 20 +++++++++++--------
19 files changed, 57 insertions(+), 24 deletions(-)
--
2.25.0
2
17
For this series,
Reviewed-by: Xie XiuQi <xiexiuqi(a)huawei.com>
-----邮件原件-----
发件人: chenjun (AM)
发送时间: 2020年12月23日 10:03
收件人: kernel(a)openeuler.org
抄送: Xiangrui (Euler) <rui.xiang(a)huawei.com>; Guohanjun (Hanjun Guo) <guohanjun(a)huawei.com>; Xiexiuqi <xiexiuqi(a)huawei.com>
主题: [PATCH OLK-5.10 0/6] Support for printing dirty pages
*** BLURB HERE ***
yu kuai (6):
fs/dirty_pages: dump the number of dirty pages for each inode
fs/dirty_pages: fix index out of bounds and integer overflow
fs/dirty_pages: fix wrong 'buff_num' after invalid input
fs/dirty_pages: Adjust position of some code to improve the code
fs/dirty_pages: fix kernel panic in concurrency mode
fs/dirty_pages: remove set but not used variable 'm'
fs/Makefile | 1 +
fs/dirty_pages.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 467 insertions(+)
create mode 100644 fs/dirty_pages.c
--
2.25.0
1
0
[PATCH kernel-4.19 01/24] net: hns3: modify location of one print information
by Yang Yingliang 23 Dec '20
by Yang Yingliang 23 Dec '20
23 Dec '20
From: Junxin Chen <chenjunxin1(a)huawei.com>
driver inclusion
category: cleanup
bugzilla: NA
CVE: NA
----------------------------
This patch modifies location of one print information.
Signed-off-by: Junxin Chen <chenjunxin1(a)huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2(a)huawei.com>
Reviewed-by: Peng Li <lipeng321(a)huawei.com>
Signed-off-by: Yonglong Liu <liuyonglong(a)huawei.com>
Reviewed-by: Yongxin Li <liyongxin1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 082625de7a30..2c1c0efad80e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3454,10 +3454,10 @@ static void hclge_do_reset(struct hclge_dev *hdev)
switch (hdev->reset_type) {
case HNAE3_GLOBAL_RESET:
+ dev_info(&pdev->dev, "global reset requested\n");
val = hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG);
hnae3_set_bit(val, HCLGE_GLOBAL_RESET_BIT, 1);
hclge_write_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG, val);
- dev_info(&pdev->dev, "global reset requested\n");
break;
case HNAE3_FUNC_RESET:
dev_info(&pdev->dev, "PF reset requested\n");
--
2.25.1
1
23
[PATCH kernel-4.19 1/2] Page flags: Add reserved page flags for future extension
by Yang Yingliang 23 Dec '20
by Yang Yingliang 23 Dec '20
23 Dec '20
From: Xiangyou Xie <xiexiangyou(a)huawei.com>
euleros inclusion
category: feature
bugzilla: 46840
CVE: NA
-------------------------------------------------
Add reserved page flags for internal extension. For the new page
flags which backported from kernel upstream, place them
behind the the reserved page flags.
Signed-off-by: Xiangyou Xie <xiexiangyou(a)huawei.com>
Reviewed-by: Zenghui Yu <yuzenghui(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/page-flags.h | 8 ++++++++
include/trace/events/mmflags.h | 4 +++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 17eeaf76259b..0d395970a988 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -103,6 +103,14 @@ enum pageflags {
PG_idle,
#endif
PG_percpu_ref,
+
+ /* Add reserved page flags for internal extension. For the new page
+ * flags which backported from kernel upstream, please place them
+ * behind the the reserved page flags.
+ */
+ PG_reserve_pgflag_0,
+ PG_reserve_pgflag_1,
+
__NR_PAGEFLAGS,
/* Filesystems */
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index 894305dad41e..d8965ccb9c4b 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -106,7 +106,9 @@ IF_HAVE_PG_UNCACHED(PG_uncached, "uncached" ) \
IF_HAVE_PG_HWPOISON(PG_hwpoison, "hwpoison" ) \
IF_HAVE_PG_IDLE(PG_young, "young" ) \
IF_HAVE_PG_IDLE(PG_idle, "idle"), \
- {1UL << PG_percpu_ref, "percpu_ref" }
+ {1UL << PG_percpu_ref, "percpu_ref" }, \
+ {1UL << PG_reserve_pgflag_0, "reserve_pgflag_0"}, \
+ {1UL << PG_reserve_pgflag_1, "reserve_pgflag_1"}
#define show_page_flags(flags) \
(flags) ? __print_flags(flags, "|", \
--
2.25.1
1
1
[PATCH 01/10] genirq, sched/isolation: Isolate from handling managed interrupts
by Yang Yingliang 23 Dec '20
by Yang Yingliang 23 Dec '20
23 Dec '20
From: Ming Lei <ming.lei(a)redhat.com>
mainline inclusion
from mainline-v5.6-rc1
commit 11ea68f553e244851d15793a7fa33a97c46d8271
category: bugfix
bugzilla: 45956
CVE: NA
--------------------------------
The affinity of managed interrupts is completely handled in the kernel and
cannot be changed via the /proc/irq/* interfaces from user space. As the
kernel tries to spread out interrupts evenly accross CPUs on x86 to prevent
vector exhaustion, it can happen that a managed interrupt whose affinity
mask contains both isolated and housekeeping CPUs is routed to an isolated
CPU. As a consequence IO submitted on a housekeeping CPU causes interrupts
on the isolated CPU.
Add a new sub-parameter 'managed_irq' for 'isolcpus' and the corresponding
logic in the interrupt affinity selection code.
The subparameter indicates to the interrupt affinity selection logic that
it should try to avoid the above scenario.
This isolation is best effort and only effective if the automatically
assigned interrupt mask of a device queue contains isolated and
housekeeping CPUs. If housekeeping CPUs are online then such interrupts are
directed to the housekeeping CPU so that IO submitted on the housekeeping
CPU cannot disturb the isolated CPU.
If a queue's affinity mask contains only isolated CPUs then this parameter
has no effect on the interrupt routing decision, though interrupts are only
happening when tasks running on those isolated CPUs submit IO. IO submitted
on housekeeping CPUs has no influence on those queues.
If the affinity mask contains both housekeeping and isolated CPUs, but none
of the contained housekeeping CPUs is online, then the interrupt is also
routed to an isolated CPU. Interrupts are only delivered when one of the
isolated CPUs in the affinity mask submits IO. If one of the contained
housekeeping CPUs comes online, the CPU hotplug logic migrates the
interrupt automatically back to the upcoming housekeeping CPU. Depending on
the type of interrupt controller, this can require that at least one
interrupt is delivered to the isolated CPU in order to complete the
migration.
[ tglx: Removed unused parameter, added and edited comments/documentation
and rephrased the changelog so it contains more details. ]
Signed-off-by: Ming Lei <ming.lei(a)redhat.com>
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Link: https://lore.kernel.org/r/20200120091625.17912-1-ming.lei@redhat.com
Signed-off-by: Liu Chao <liuchao173(a)huawei.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
.../admin-guide/kernel-parameters.txt | 26 +++++++++++-
include/linux/sched/isolation.h | 7 ++++
kernel/irq/cpuhotplug.c | 21 +++++++++-
kernel/irq/manage.c | 41 ++++++++++++++++++-
kernel/sched/isolation.c | 12 ++++++
5 files changed, 102 insertions(+), 5 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 60c06c7d243d..a0e84095a1a5 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1911,9 +1911,31 @@
<cpu number> begins at 0 and the maximum value is
"number of CPUs in system - 1".
- The format of <cpu-list> is described above.
-
+ managed_irq
+
+ Isolate from being targeted by managed interrupts
+ which have an interrupt mask containing isolated
+ CPUs. The affinity of managed interrupts is
+ handled by the kernel and cannot be changed via
+ the /proc/irq/* interfaces.
+
+ This isolation is best effort and only effective
+ if the automatically assigned interrupt mask of a
+ device queue contains isolated and housekeeping
+ CPUs. If housekeeping CPUs are online then such
+ interrupts are directed to the housekeeping CPU
+ so that IO submitted on the housekeeping CPU
+ cannot disturb the isolated CPU.
+
+ If a queue's affinity mask contains only isolated
+ CPUs then this parameter has no effect on the
+ interrupt routing decision, though interrupts are
+ only delivered when tasks running on those
+ isolated CPUs submit IO. IO submitted on
+ housekeeping CPUs has no influence on those
+ queues.
+ The format of <cpu-list> is described above.
iucv= [HW,NET]
diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h
index 4a6582c27dea..461e1f6ab3eb 100644
--- a/include/linux/sched/isolation.h
+++ b/include/linux/sched/isolation.h
@@ -13,12 +13,14 @@ enum hk_flags {
HK_FLAG_TICK = (1 << 4),
HK_FLAG_DOMAIN = (1 << 5),
HK_FLAG_WQ = (1 << 6),
+ HK_FLAG_MANAGED_IRQ = (1 << 7),
};
#ifdef CONFIG_CPU_ISOLATION
DECLARE_STATIC_KEY_FALSE(housekeeping_overriden);
extern int housekeeping_any_cpu(enum hk_flags flags);
extern const struct cpumask *housekeeping_cpumask(enum hk_flags flags);
+extern bool housekeeping_enabled(enum hk_flags flags);
extern void housekeeping_affine(struct task_struct *t, enum hk_flags flags);
extern bool housekeeping_test_cpu(int cpu, enum hk_flags flags);
extern void __init housekeeping_init(void);
@@ -35,6 +37,11 @@ static inline const struct cpumask *housekeeping_cpumask(enum hk_flags flags)
return cpu_possible_mask;
}
+static inline bool housekeeping_enabled(enum hk_flags flags)
+{
+ return false;
+}
+
static inline void housekeeping_affine(struct task_struct *t,
enum hk_flags flags) { }
static inline void housekeeping_init(void) { }
diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c
index 6c7ca2e983a5..02236b13b359 100644
--- a/kernel/irq/cpuhotplug.c
+++ b/kernel/irq/cpuhotplug.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/ratelimit.h>
#include <linux/irq.h>
+#include <linux/sched/isolation.h>
#include "internals.h"
@@ -171,6 +172,20 @@ void irq_migrate_all_off_this_cpu(void)
}
}
+static bool hk_should_isolate(struct irq_data *data, unsigned int cpu)
+{
+ const struct cpumask *hk_mask;
+
+ if (!housekeeping_enabled(HK_FLAG_MANAGED_IRQ))
+ return false;
+
+ hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ);
+ if (cpumask_subset(irq_data_get_effective_affinity_mask(data), hk_mask))
+ return false;
+
+ return cpumask_test_cpu(cpu, hk_mask);
+}
+
static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
@@ -188,9 +203,11 @@ static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu)
/*
* If the interrupt can only be directed to a single target
* CPU then it is already assigned to a CPU in the affinity
- * mask. No point in trying to move it around.
+ * mask. No point in trying to move it around unless the
+ * isolation mechanism requests to move it to an upcoming
+ * housekeeping CPU.
*/
- if (!irqd_is_single_target(data))
+ if (!irqd_is_single_target(data) || hk_should_isolate(data, cpu))
irq_set_affinity_locked(data, affinity, false);
}
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a8c66acee82a..34eda1e772fa 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/sched/rt.h>
#include <linux/sched/task.h>
+#include <linux/sched/isolation.h>
#include <uapi/linux/sched/types.h>
#include <linux/task_work.h>
@@ -227,7 +228,45 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
if (!chip || !chip->irq_set_affinity)
return -EINVAL;
- ret = chip->irq_set_affinity(data, mask, force);
+ /*
+ * If this is a managed interrupt and housekeeping is enabled on
+ * it check whether the requested affinity mask intersects with
+ * a housekeeping CPU. If so, then remove the isolated CPUs from
+ * the mask and just keep the housekeeping CPU(s). This prevents
+ * the affinity setter from routing the interrupt to an isolated
+ * CPU to avoid that I/O submitted from a housekeeping CPU causes
+ * interrupts on an isolated one.
+ *
+ * If the masks do not intersect or include online CPU(s) then
+ * keep the requested mask. The isolated target CPUs are only
+ * receiving interrupts when the I/O operation was submitted
+ * directly from them.
+ *
+ * If all housekeeping CPUs in the affinity mask are offline, the
+ * interrupt will be migrated by the CPU hotplug code once a
+ * housekeeping CPU which belongs to the affinity mask comes
+ * online.
+ */
+ if (irqd_affinity_is_managed(data) &&
+ housekeeping_enabled(HK_FLAG_MANAGED_IRQ)) {
+ const struct cpumask *hk_mask, *prog_mask;
+
+ static DEFINE_RAW_SPINLOCK(tmp_mask_lock);
+ static struct cpumask tmp_mask;
+
+ hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ);
+
+ raw_spin_lock(&tmp_mask_lock);
+ cpumask_and(&tmp_mask, mask, hk_mask);
+ if (!cpumask_intersects(&tmp_mask, cpu_online_mask))
+ prog_mask = mask;
+ else
+ prog_mask = &tmp_mask;
+ ret = chip->irq_set_affinity(data, prog_mask, force);
+ raw_spin_unlock(&tmp_mask_lock);
+ } else {
+ ret = chip->irq_set_affinity(data, mask, force);
+ }
switch (ret) {
case IRQ_SET_MASK_OK:
case IRQ_SET_MASK_OK_DONE:
diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
index e6802181900f..6e85049d68cf 100644
--- a/kernel/sched/isolation.c
+++ b/kernel/sched/isolation.c
@@ -13,6 +13,12 @@ EXPORT_SYMBOL_GPL(housekeeping_overriden);
static cpumask_var_t housekeeping_mask;
static unsigned int housekeeping_flags;
+bool housekeeping_enabled(enum hk_flags flags)
+{
+ return !!(housekeeping_flags & flags);
+}
+EXPORT_SYMBOL_GPL(housekeeping_enabled);
+
int housekeeping_any_cpu(enum hk_flags flags)
{
if (static_branch_unlikely(&housekeeping_overriden))
@@ -140,6 +146,12 @@ static int __init housekeeping_isolcpus_setup(char *str)
continue;
}
+ if (!strncmp(str, "managed_irq,", 12)) {
+ str += 12;
+ flags |= HK_FLAG_MANAGED_IRQ;
+ continue;
+ }
+
pr_warn("isolcpus: Error, unknown flag\n");
return 0;
}
--
2.25.1
1
9
[PATCH 01/10] genirq, sched/isolation: Isolate from handling managed interrupts
by Yang Yingliang 23 Dec '20
by Yang Yingliang 23 Dec '20
23 Dec '20
From: Ming Lei <ming.lei(a)redhat.com>
mainline inclusion
from mainline-v5.6-rc1
commit 11ea68f553e244851d15793a7fa33a97c46d8271
category: bugfix
bugzilla: 45956
CVE: NA
--------------------------------
The affinity of managed interrupts is completely handled in the kernel and
cannot be changed via the /proc/irq/* interfaces from user space. As the
kernel tries to spread out interrupts evenly accross CPUs on x86 to prevent
vector exhaustion, it can happen that a managed interrupt whose affinity
mask contains both isolated and housekeeping CPUs is routed to an isolated
CPU. As a consequence IO submitted on a housekeeping CPU causes interrupts
on the isolated CPU.
Add a new sub-parameter 'managed_irq' for 'isolcpus' and the corresponding
logic in the interrupt affinity selection code.
The subparameter indicates to the interrupt affinity selection logic that
it should try to avoid the above scenario.
This isolation is best effort and only effective if the automatically
assigned interrupt mask of a device queue contains isolated and
housekeeping CPUs. If housekeeping CPUs are online then such interrupts are
directed to the housekeeping CPU so that IO submitted on the housekeeping
CPU cannot disturb the isolated CPU.
If a queue's affinity mask contains only isolated CPUs then this parameter
has no effect on the interrupt routing decision, though interrupts are only
happening when tasks running on those isolated CPUs submit IO. IO submitted
on housekeeping CPUs has no influence on those queues.
If the affinity mask contains both housekeeping and isolated CPUs, but none
of the contained housekeeping CPUs is online, then the interrupt is also
routed to an isolated CPU. Interrupts are only delivered when one of the
isolated CPUs in the affinity mask submits IO. If one of the contained
housekeeping CPUs comes online, the CPU hotplug logic migrates the
interrupt automatically back to the upcoming housekeeping CPU. Depending on
the type of interrupt controller, this can require that at least one
interrupt is delivered to the isolated CPU in order to complete the
migration.
[ tglx: Removed unused parameter, added and edited comments/documentation
and rephrased the changelog so it contains more details. ]
Signed-off-by: Ming Lei <ming.lei(a)redhat.com>
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Link: https://lore.kernel.org/r/20200120091625.17912-1-ming.lei@redhat.com
Signed-off-by: Liu Chao <liuchao173(a)huawei.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
.../admin-guide/kernel-parameters.txt | 26 +++++++++++-
include/linux/sched/isolation.h | 7 ++++
kernel/irq/cpuhotplug.c | 21 +++++++++-
kernel/irq/manage.c | 41 ++++++++++++++++++-
kernel/sched/isolation.c | 12 ++++++
5 files changed, 102 insertions(+), 5 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 60c06c7d243d..a0e84095a1a5 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1911,9 +1911,31 @@
<cpu number> begins at 0 and the maximum value is
"number of CPUs in system - 1".
- The format of <cpu-list> is described above.
-
+ managed_irq
+
+ Isolate from being targeted by managed interrupts
+ which have an interrupt mask containing isolated
+ CPUs. The affinity of managed interrupts is
+ handled by the kernel and cannot be changed via
+ the /proc/irq/* interfaces.
+
+ This isolation is best effort and only effective
+ if the automatically assigned interrupt mask of a
+ device queue contains isolated and housekeeping
+ CPUs. If housekeeping CPUs are online then such
+ interrupts are directed to the housekeeping CPU
+ so that IO submitted on the housekeeping CPU
+ cannot disturb the isolated CPU.
+
+ If a queue's affinity mask contains only isolated
+ CPUs then this parameter has no effect on the
+ interrupt routing decision, though interrupts are
+ only delivered when tasks running on those
+ isolated CPUs submit IO. IO submitted on
+ housekeeping CPUs has no influence on those
+ queues.
+ The format of <cpu-list> is described above.
iucv= [HW,NET]
diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h
index 4a6582c27dea..461e1f6ab3eb 100644
--- a/include/linux/sched/isolation.h
+++ b/include/linux/sched/isolation.h
@@ -13,12 +13,14 @@ enum hk_flags {
HK_FLAG_TICK = (1 << 4),
HK_FLAG_DOMAIN = (1 << 5),
HK_FLAG_WQ = (1 << 6),
+ HK_FLAG_MANAGED_IRQ = (1 << 7),
};
#ifdef CONFIG_CPU_ISOLATION
DECLARE_STATIC_KEY_FALSE(housekeeping_overriden);
extern int housekeeping_any_cpu(enum hk_flags flags);
extern const struct cpumask *housekeeping_cpumask(enum hk_flags flags);
+extern bool housekeeping_enabled(enum hk_flags flags);
extern void housekeeping_affine(struct task_struct *t, enum hk_flags flags);
extern bool housekeeping_test_cpu(int cpu, enum hk_flags flags);
extern void __init housekeeping_init(void);
@@ -35,6 +37,11 @@ static inline const struct cpumask *housekeeping_cpumask(enum hk_flags flags)
return cpu_possible_mask;
}
+static inline bool housekeeping_enabled(enum hk_flags flags)
+{
+ return false;
+}
+
static inline void housekeeping_affine(struct task_struct *t,
enum hk_flags flags) { }
static inline void housekeeping_init(void) { }
diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c
index 6c7ca2e983a5..02236b13b359 100644
--- a/kernel/irq/cpuhotplug.c
+++ b/kernel/irq/cpuhotplug.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/ratelimit.h>
#include <linux/irq.h>
+#include <linux/sched/isolation.h>
#include "internals.h"
@@ -171,6 +172,20 @@ void irq_migrate_all_off_this_cpu(void)
}
}
+static bool hk_should_isolate(struct irq_data *data, unsigned int cpu)
+{
+ const struct cpumask *hk_mask;
+
+ if (!housekeeping_enabled(HK_FLAG_MANAGED_IRQ))
+ return false;
+
+ hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ);
+ if (cpumask_subset(irq_data_get_effective_affinity_mask(data), hk_mask))
+ return false;
+
+ return cpumask_test_cpu(cpu, hk_mask);
+}
+
static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
@@ -188,9 +203,11 @@ static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu)
/*
* If the interrupt can only be directed to a single target
* CPU then it is already assigned to a CPU in the affinity
- * mask. No point in trying to move it around.
+ * mask. No point in trying to move it around unless the
+ * isolation mechanism requests to move it to an upcoming
+ * housekeeping CPU.
*/
- if (!irqd_is_single_target(data))
+ if (!irqd_is_single_target(data) || hk_should_isolate(data, cpu))
irq_set_affinity_locked(data, affinity, false);
}
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a8c66acee82a..34eda1e772fa 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/sched/rt.h>
#include <linux/sched/task.h>
+#include <linux/sched/isolation.h>
#include <uapi/linux/sched/types.h>
#include <linux/task_work.h>
@@ -227,7 +228,45 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
if (!chip || !chip->irq_set_affinity)
return -EINVAL;
- ret = chip->irq_set_affinity(data, mask, force);
+ /*
+ * If this is a managed interrupt and housekeeping is enabled on
+ * it check whether the requested affinity mask intersects with
+ * a housekeeping CPU. If so, then remove the isolated CPUs from
+ * the mask and just keep the housekeeping CPU(s). This prevents
+ * the affinity setter from routing the interrupt to an isolated
+ * CPU to avoid that I/O submitted from a housekeeping CPU causes
+ * interrupts on an isolated one.
+ *
+ * If the masks do not intersect or include online CPU(s) then
+ * keep the requested mask. The isolated target CPUs are only
+ * receiving interrupts when the I/O operation was submitted
+ * directly from them.
+ *
+ * If all housekeeping CPUs in the affinity mask are offline, the
+ * interrupt will be migrated by the CPU hotplug code once a
+ * housekeeping CPU which belongs to the affinity mask comes
+ * online.
+ */
+ if (irqd_affinity_is_managed(data) &&
+ housekeeping_enabled(HK_FLAG_MANAGED_IRQ)) {
+ const struct cpumask *hk_mask, *prog_mask;
+
+ static DEFINE_RAW_SPINLOCK(tmp_mask_lock);
+ static struct cpumask tmp_mask;
+
+ hk_mask = housekeeping_cpumask(HK_FLAG_MANAGED_IRQ);
+
+ raw_spin_lock(&tmp_mask_lock);
+ cpumask_and(&tmp_mask, mask, hk_mask);
+ if (!cpumask_intersects(&tmp_mask, cpu_online_mask))
+ prog_mask = mask;
+ else
+ prog_mask = &tmp_mask;
+ ret = chip->irq_set_affinity(data, prog_mask, force);
+ raw_spin_unlock(&tmp_mask_lock);
+ } else {
+ ret = chip->irq_set_affinity(data, mask, force);
+ }
switch (ret) {
case IRQ_SET_MASK_OK:
case IRQ_SET_MASK_OK_DONE:
diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
index e6802181900f..6e85049d68cf 100644
--- a/kernel/sched/isolation.c
+++ b/kernel/sched/isolation.c
@@ -13,6 +13,12 @@ EXPORT_SYMBOL_GPL(housekeeping_overriden);
static cpumask_var_t housekeeping_mask;
static unsigned int housekeeping_flags;
+bool housekeeping_enabled(enum hk_flags flags)
+{
+ return !!(housekeeping_flags & flags);
+}
+EXPORT_SYMBOL_GPL(housekeeping_enabled);
+
int housekeeping_any_cpu(enum hk_flags flags)
{
if (static_branch_unlikely(&housekeeping_overriden))
@@ -140,6 +146,12 @@ static int __init housekeeping_isolcpus_setup(char *str)
continue;
}
+ if (!strncmp(str, "managed_irq,", 12)) {
+ str += 12;
+ flags |= HK_FLAG_MANAGED_IRQ;
+ continue;
+ }
+
pr_warn("isolcpus: Error, unknown flag\n");
return 0;
}
--
2.25.1
1
2
From: Mingwang Li <limingwang(a)huawei.com>
euleros inclusion
category: feature
feature: initial KVM RISC-V support
bugzilla: 46845
CVE: NA
This series adds initial KVM RISC-V support. Currently, we are able to
boot Linux on RV64/RV32 Guest with multiple VCPUs.
This series can be found in riscv_kvm_v15 branch at:
https//github.com/avpatel/linux.git
Changes since v2
- fix build error
Changes since v1
- follow guileline for submiting patches to openEuler
- add the testing result in this issue
Reference: https://gitee.com/openeuler/kernel/issues/I26X9V
Alistair Francis (1):
Revert "riscv: Use latest system call ABI"
Anup Patel (19):
RISC-V: Add fragmented config for debug options
RISC-V: Enable CPU Hotplug in defconfigs
RISC-V: Add Microchip PolarFire kconfig option
RISC-V: Initial DTS for Microchip ICICLE board
RISC-V: Enable drivers for Microchip PolarFire ICICLE board
RISC-V: Add hypervisor extension related CSR defines
RISC-V: Add initial skeletal KVM support
RISC-V: KVM: Implement VCPU create, init and destroy functions
RISC-V: KVM: Implement VCPU interrupts and requests handling
RISC-V: KVM: Implement KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls
RISC-V: KVM: Implement VCPU world-switch
RISC-V: KVM: Handle MMIO exits for VCPU
RISC-V: KVM: Handle WFI exits for VCPU
RISC-V: KVM: Implement VMID allocator
RISC-V: KVM: Implement stage2 page table programming
RISC-V: KVM: Implement MMU notifiers
RISC-V: KVM: Document RISC-V specific parts of KVM API
RISC-V: KVM: Add MAINTAINERS entry
RISC-V: Enable KVM for RV64 and RV32
Atish Patra (4):
RISC-V: KVM: Add timer functionality
RISC-V: KVM: FP lazy save/restore
RISC-V: KVM: Implement ONE REG interface for FP registers
RISC-V: KVM: Add SBI v0.1 support
Mingwang Li (1):
RISCV: KVM: fix bug in migration
m34782 (1):
Microchip Polarfire SoC Clock Driver
Documentation/virt/kvm/api.rst | 193 +++-
MAINTAINERS | 11 +
arch/riscv/Kconfig | 2 +
arch/riscv/Kconfig.socs | 7 +
arch/riscv/Makefile | 2 +
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/microchip/Makefile | 2 +
.../boot/dts/microchip/icicle-kit-es.dts | 307 +++++
arch/riscv/configs/defconfig | 30 +-
arch/riscv/configs/extra_debug.config | 21 +
arch/riscv/configs/rv32_defconfig | 26 +-
arch/riscv/include/asm/csr.h | 89 ++
arch/riscv/include/asm/kvm_host.h | 278 +++++
arch/riscv/include/asm/kvm_types.h | 7 +
arch/riscv/include/asm/kvm_vcpu_timer.h | 44 +
arch/riscv/include/asm/pgtable-bits.h | 1 +
arch/riscv/include/uapi/asm/kvm.h | 128 +++
arch/riscv/include/uapi/asm/unistd.h | 5 +-
arch/riscv/kernel/asm-offsets.c | 156 +++
arch/riscv/kvm/Kconfig | 36 +
arch/riscv/kvm/Makefile | 15 +
arch/riscv/kvm/main.c | 118 ++
arch/riscv/kvm/mmu.c | 860 ++++++++++++++
arch/riscv/kvm/tlb.S | 74 ++
arch/riscv/kvm/vcpu.c | 1012 +++++++++++++++++
arch/riscv/kvm/vcpu_exit.c | 701 ++++++++++++
arch/riscv/kvm/vcpu_sbi.c | 173 +++
arch/riscv/kvm/vcpu_switch.S | 400 +++++++
arch/riscv/kvm/vcpu_timer.c | 225 ++++
arch/riscv/kvm/vm.c | 81 ++
arch/riscv/kvm/vmid.c | 120 ++
drivers/clk/Kconfig | 5 +
drivers/clk/Makefile | 1 +
drivers/clk/microchip/Makefile | 2 +
drivers/clk/microchip/clk-pfsoc.c | 508 +++++++++
drivers/clocksource/timer-riscv.c | 8 +
include/clocksource/timer-riscv.h | 16 +
include/uapi/linux/kvm.h | 8 +
38 files changed, 5619 insertions(+), 54 deletions(-)
create mode 100644 arch/riscv/boot/dts/microchip/Makefile
create mode 100644 arch/riscv/boot/dts/microchip/icicle-kit-es.dts
create mode 100644 arch/riscv/configs/extra_debug.config
create mode 100644 arch/riscv/include/asm/kvm_host.h
create mode 100644 arch/riscv/include/asm/kvm_types.h
create mode 100644 arch/riscv/include/asm/kvm_vcpu_timer.h
create mode 100644 arch/riscv/include/uapi/asm/kvm.h
create mode 100644 arch/riscv/kvm/Kconfig
create mode 100644 arch/riscv/kvm/Makefile
create mode 100644 arch/riscv/kvm/main.c
create mode 100644 arch/riscv/kvm/mmu.c
create mode 100644 arch/riscv/kvm/tlb.S
create mode 100644 arch/riscv/kvm/vcpu.c
create mode 100644 arch/riscv/kvm/vcpu_exit.c
create mode 100644 arch/riscv/kvm/vcpu_sbi.c
create mode 100644 arch/riscv/kvm/vcpu_switch.S
create mode 100644 arch/riscv/kvm/vcpu_timer.c
create mode 100644 arch/riscv/kvm/vm.c
create mode 100644 arch/riscv/kvm/vmid.c
create mode 100644 drivers/clk/microchip/clk-pfsoc.c
create mode 100644 include/clocksource/timer-riscv.h
--
2.19.1
3
28
22 Dec '20
From: Kefeng Wang <wangkefeng.wang(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 46856
CVE: NA
---------------------------
The start_pfn and end_pfn are already available in move_freepages_block(),
there is no need to go back and forth between page and pfn in move_freepages
and move_freepages_block, and pfn_valid_within() should validate pfn first
before touching the page.
Signed-off-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
---
mm/page_alloc.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index eaa227a479e4..636afce90efa 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2361,19 +2361,21 @@ static inline struct page *__rmqueue_cma_fallback(struct zone *zone,
* boundary. If alignment is required, use move_freepages_block()
*/
static int move_freepages(struct zone *zone,
- struct page *start_page, struct page *end_page,
+ unsigned long start_pfn, unsigned long end_pfn,
int migratetype, int *num_movable)
{
struct page *page;
+ unsigned long pfn;
unsigned int order;
int pages_moved = 0;
- for (page = start_page; page <= end_page;) {
- if (!pfn_valid_within(page_to_pfn(page))) {
- page++;
+ for (pfn = start_pfn; pfn <= end_pfn;) {
+ if (!pfn_valid_within(pfn)) {
+ pfn++;
continue;
}
+ page = pfn_to_page(pfn);
if (!PageBuddy(page)) {
/*
* We assume that pages that could be isolated for
@@ -2383,8 +2385,7 @@ static int move_freepages(struct zone *zone,
if (num_movable &&
(PageLRU(page) || __PageMovable(page)))
(*num_movable)++;
-
- page++;
+ pfn++;
continue;
}
@@ -2394,7 +2395,7 @@ static int move_freepages(struct zone *zone,
order = buddy_order(page);
move_to_free_list(page, zone, order, migratetype);
- page += 1 << order;
+ pfn += 1 << order;
pages_moved += 1 << order;
}
@@ -2404,25 +2405,22 @@ static int move_freepages(struct zone *zone,
int move_freepages_block(struct zone *zone, struct page *page,
int migratetype, int *num_movable)
{
- unsigned long start_pfn, end_pfn;
- struct page *start_page, *end_page;
+ unsigned long start_pfn, end_pfn, pfn;
if (num_movable)
*num_movable = 0;
- start_pfn = page_to_pfn(page);
- start_pfn = start_pfn & ~(pageblock_nr_pages-1);
- start_page = pfn_to_page(start_pfn);
- end_page = start_page + pageblock_nr_pages - 1;
+ pfn = page_to_pfn(page);
+ start_pfn = pfn & ~(pageblock_nr_pages - 1);
end_pfn = start_pfn + pageblock_nr_pages - 1;
/* Do not cross zone boundaries */
if (!zone_spans_pfn(zone, start_pfn))
- start_page = page;
+ start_pfn = pfn;
if (!zone_spans_pfn(zone, end_pfn))
return 0;
- return move_freepages(zone, start_page, end_page, migratetype,
+ return move_freepages(zone, start_pfn, end_pfn, migratetype,
num_movable);
}
--
2.25.0
1
0
*** BLURB HERE ***
Andrew Pinski (3):
arm64: rename COMPAT to AARCH32_EL0
arm64: uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
arm64:ilp32: add ARM64_ILP32 to Kconfig
Dave Martin (1):
arm64: signal: Make parse_user_sigframe() independent of rt_sigframe
layout
James Morse (1):
ptrace: Add compat PTRACE_{G,S}ETSIGMASK handlers
Philipp Tomsich (1):
arm64:ilp32: add vdso-ilp32 and use for signal return
Xiongfeng Wang (4):
arm64: rename functions that reference compat term
arm64: secomp: fix the secure computing mode 1 syscall check for ilp32
ilp32: avoid clearing upper 32 bits of syscall return value for ilp32
ilp32: skip ARM erratum 1418040 for ilp32 application
Yury Norov (14):
thread: move thread bits accessors to separated file
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
arm64: introduce is_a32_compat_{task,thread} for AArch32 compat
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce AUDIT_ARCH_AARCH64ILP32 for ilp32
arm64: introduce binfmt_elf32.c
arm64: change compat_elf_hwcap and compat_elf_hwcap2 prefix to a32
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ilp32: share aarch32 syscall handlers
arm64: ilp32: introduce syscall table for ILP32
arm64: signal: share lp64 signal structures and routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific sigframe and ucontext
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
Documentation/arm64/ilp32.txt | 52 +++
arch/arm64/Kconfig | 20 +-
arch/arm64/Makefile | 3 +
arch/arm64/include/asm/arch_timer.h | 4 +-
arch/arm64/include/asm/compat.h | 19 +-
arch/arm64/include/asm/elf.h | 37 +-
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/ftrace.h | 2 +-
arch/arm64/include/asm/hwcap.h | 8 +-
arch/arm64/include/asm/is_compat.h | 78 ++++
arch/arm64/include/asm/processor.h | 15 +-
arch/arm64/include/asm/ptrace.h | 10 +-
arch/arm64/include/asm/seccomp.h | 32 +-
arch/arm64/include/asm/signal32.h | 31 +-
arch/arm64/include/asm/signal32_common.h | 13 +
arch/arm64/include/asm/signal_common.h | 303 +++++++++++++++
arch/arm64/include/asm/signal_ilp32.h | 23 ++
arch/arm64/include/asm/syscall.h | 17 +-
arch/arm64/include/asm/thread_info.h | 4 +-
arch/arm64/include/asm/unistd.h | 5 +
arch/arm64/include/asm/vdso.h | 6 +
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/include/uapi/asm/unistd.h | 15 +-
arch/arm64/kernel/Makefile | 8 +-
arch/arm64/kernel/armv8_deprecated.c | 6 +-
arch/arm64/kernel/asm-offsets.c | 13 +-
arch/arm64/kernel/binfmt_elf32.c | 34 ++
arch/arm64/kernel/binfmt_ilp32.c | 88 +++++
arch/arm64/kernel/cpufeature.c | 30 +-
arch/arm64/kernel/cpuinfo.c | 18 +-
arch/arm64/kernel/debug-monitors.c | 4 +-
arch/arm64/kernel/entry-common.c | 4 +-
arch/arm64/kernel/entry.S | 6 +-
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 8 +-
arch/arm64/kernel/perf_callchain.c | 28 +-
arch/arm64/kernel/perf_regs.c | 4 +-
arch/arm64/kernel/process.c | 15 +-
arch/arm64/kernel/proton-pack.c | 2 +-
arch/arm64/kernel/ptrace.c | 38 +-
arch/arm64/kernel/signal.c | 348 ++++--------------
arch/arm64/kernel/signal32.c | 97 ++---
arch/arm64/kernel/signal32_common.c | 37 ++
arch/arm64/kernel/signal_ilp32.c | 67 ++++
arch/arm64/kernel/sys32.c | 104 +-----
arch/arm64/kernel/sys32_common.c | 106 ++++++
arch/arm64/kernel/sys_compat.c | 12 +-
arch/arm64/kernel/sys_ilp32.c | 82 +++++
arch/arm64/kernel/syscall.c | 39 +-
arch/arm64/kernel/traps.c | 5 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 108 ++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 22 ++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 88 +++++
arch/arm64/kernel/vdso.c | 50 ++-
include/linux/sched.h | 1 +
include/linux/thread_bits.h | 87 +++++
include/linux/thread_info.h | 75 +---
include/uapi/linux/audit.h | 1 +
kernel/ptrace.c | 52 ++-
60 files changed, 1673 insertions(+), 726 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
create mode 100644 arch/arm64/include/asm/is_compat.h
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/include/asm/signal_common.h
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
create mode 100644 arch/arm64/kernel/signal32_common.c
create mode 100644 arch/arm64/kernel/signal_ilp32.c
create mode 100644 arch/arm64/kernel/sys32_common.c
create mode 100644 arch/arm64/kernel/sys_ilp32.c
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
create mode 100644 include/linux/thread_bits.h
--
2.25.0
2
25
[PATCH kernel-4.19 01/25] ascend: share_pool: make the function share_k2u_to_spg work
by Yang Yingliang 22 Dec '20
by Yang Yingliang 22 Dec '20
22 Dec '20
From: Ding Tianhong <dingtianhong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
The share_k2u_to_spg was designed to translate the kernel virtual
address to user level address and share to the whole group, but
tht function use the uncorrect file to mmap the memory region,
it was not really work for whole group, and will consume more memory,
fix this problem to use the correct hugepage file and make share to
the whole group for each task.
Signed-off-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/share_pool.c | 117 +++++++++++++++++++++++++++++++++++-------------
1 file changed, 87 insertions(+), 30 deletions(-)
diff --git a/mm/share_pool.c b/mm/share_pool.c
index f8dfbe80968b..a83254200e33 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -267,7 +267,10 @@ static int spa_dec_usage(enum spa_type type, unsigned long size, bool is_dvpp)
}
static unsigned long sp_mmap(struct mm_struct *mm, struct file *file,
- struct sp_area *spa, unsigned long *populate);
+ struct sp_area *spa, unsigned long *populate);
+static void sp_munmap(struct mm_struct *mm, unsigned long addr, unsigned long size);
+static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
+ struct mm_struct *mm);
static void free_sp_group_id(unsigned int spg_id)
{
@@ -596,6 +599,15 @@ int sp_group_add_task(int pid, int spg_id)
atomic_inc(&spa->use_count);
spin_unlock(&sp_area_lock);
+ if (spa->type == SPA_TYPE_K2SPG && spa->kva) {
+ addr = sp_remap_kva_to_vma(spa->kva, spa, mm);
+ if (IS_ERR_VALUE(addr))
+ pr_warn("share pool: task add group remap k2u failed, ret %ld\n", addr);
+
+ spin_lock(&sp_area_lock);
+ continue;
+ }
+
down_write(&mm->mmap_sem);
addr = sp_mmap(mm, file, spa, &populate);
if (IS_ERR_VALUE(addr)) {
@@ -611,9 +623,11 @@ int sp_group_add_task(int pid, int spg_id)
if (populate) {
ret = do_mm_populate(mm, spa->va_start, populate, 0);
if (ret) {
- if (printk_ratelimit())
+ if (printk_ratelimit()) {
pr_warn("share pool: task add group failed when mm populate "
- "failed (potential no enough memory): %d\n", ret);
+ "failed (potential no enough memory): %d "
+ "spa flag is %d\n", ret, spa->type);
+ }
sp_munmap_task_areas(mm, spa->link.next);
spin_lock(&sp_area_lock);
break;
@@ -1480,12 +1494,16 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
int hsize_log = MAP_HUGE_2MB >> MAP_HUGE_SHIFT;
unsigned long addr, buf, offset;
- if (spa->is_hugepage) {
- file = hugetlb_file_setup(HUGETLB_ANON_FILE, spa_size(spa), VM_NORESERVE,
- &user, HUGETLB_ANONHUGE_INODE, hsize_log);
- if (IS_ERR(file)) {
- pr_err("share pool: file setup for k2u hugepage failed %ld\n", PTR_ERR(file));
- return PTR_ERR(file);
+ if (spg_valid(spa->spg)) {
+ file = spa_file(spa);
+ } else {
+ if (spa->is_hugepage) {
+ file = hugetlb_file_setup(HUGETLB_ANON_FILE, spa_size(spa), VM_NORESERVE,
+ &user, HUGETLB_ANONHUGE_INODE, hsize_log);
+ if (IS_ERR(file)) {
+ pr_err("share pool: file setup for k2u hugepage failed %ld\n", PTR_ERR(file));
+ return PTR_ERR(file);
+ }
}
}
@@ -1510,7 +1528,8 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
ret = remap_vmalloc_hugepage_range(vma, (void *)kva, 0);
if (ret) {
do_munmap(mm, ret_addr, spa_size(spa), NULL);
- pr_err("share pool: remap vmalloc hugepage failed, ret %d\n", ret);
+ pr_err("share pool: remap vmalloc hugepage failed, "
+ "ret %d, kva is %lx\n", ret, kva);
ret_addr = ret;
goto put_mm;
}
@@ -1538,7 +1557,7 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
up_write(&mm->mmap_sem);
mmput(mm);
put_file:
- if (file)
+ if (!spa->spg && file)
fput(file);
return ret_addr;
@@ -1615,6 +1634,35 @@ static void *sp_make_share_kva_to_spg(unsigned long kva, struct sp_area *spa,
return p;
}
+static bool vmalloc_area_set_flag(struct sp_area *spa, unsigned long kva, unsigned long flags)
+{
+ struct vm_struct *area;
+
+ area = find_vm_area((void *)kva);
+ if (area) {
+ area->flags |= flags;
+ spa->kva = kva;
+ return true;
+ }
+
+ return false;
+}
+
+static bool vmalloc_area_clr_flag(struct sp_area *spa, unsigned long kva, unsigned long flags)
+{
+ struct vm_struct *area;
+
+ spa->kva = 0;
+
+ area = find_vm_area((void *)kva);
+ if (area) {
+ area->flags &= ~flags;
+ return true;
+ }
+
+ return false;
+}
+
/**
* Share kernel memory to a specified process or sp_group
* @kva: the VA of shared kernel memory
@@ -1638,7 +1686,6 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
unsigned long size_aligned;
unsigned int page_size = PAGE_SIZE;
int ret;
- struct vm_struct *area;
if (sp_flags & ~SP_DVPP) {
if (printk_ratelimit())
@@ -1679,8 +1726,13 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
PTR_ERR(spa));
return spa;
}
+
+ if (!vmalloc_area_set_flag(spa, kva_aligned, VM_SHAREPOOL)) {
+ pr_err("%s: the kva %ld is not valid\n", __func__, kva_aligned);
+ goto out;
+ }
+
uva = sp_make_share_kva_to_task(kva_aligned, spa, pid);
- mutex_unlock(&sp_mutex);
} else if (spg_valid(spg)) {
/* k2u to group */
if (spg_id != SPG_ID_DEFAULT && spg_id != spg->id) {
@@ -1699,26 +1751,31 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
return spa;
}
+ if (!vmalloc_area_set_flag(spa, kva_aligned, VM_SHAREPOOL)) {
+ pr_err("%s: the kva %ld is not valid\n", __func__, kva_aligned);
+ goto out;
+ }
+
uva = sp_make_share_kva_to_spg(kva_aligned, spa, spg);
- mutex_unlock(&sp_mutex);
} else {
mutex_unlock(&sp_mutex);
pr_err("share pool: failed to make k2u\n");
return NULL;
}
- if (!IS_ERR(uva))
+ if (!IS_ERR(uva)) {
uva = uva + (kva - kva_aligned);
+ } else {
+ /* associate vma and spa */
+ if (!vmalloc_area_clr_flag(spa, kva_aligned, VM_SHAREPOOL))
+ pr_warn("share pool: %s: the kva %ld is not valid \n",
+ __func__, kva_aligned);
+ }
+out:
__sp_area_drop(spa);
+ mutex_unlock(&sp_mutex);
- if (!IS_ERR(uva)) {
- /* associate vma and spa */
- area = find_vm_area((void *)kva);
- if (area)
- area->flags |= VM_SHAREPOOL;
- spa->kva = kva;
- }
sp_dump_stack();
return uva;
@@ -1990,7 +2047,6 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
unsigned long uva_aligned;
unsigned long size_aligned;
unsigned int page_size;
- struct vm_struct *area;
mutex_lock(&sp_mutex);
/*
@@ -2061,7 +2117,7 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
if (printk_ratelimit())
pr_info("share pool: no need to unshare uva(to task), "
"target process mm is exiting\n");
- goto out_drop_area;
+ goto out_clr_flag;
}
if (spa->mm != mm) {
@@ -2095,7 +2151,7 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
if (printk_ratelimit())
pr_info("share pool: no need to unshare uva(to group), "
"spa doesn't belong to a sp group or group is dead\n");
- goto out_drop_area;
+ goto out_clr_flag;
}
/* alway allow kthread and dvpp channel destroy procedure */
@@ -2112,11 +2168,12 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
sp_dump_stack();
-out_drop_area:
+out_clr_flag:
/* deassociate vma and spa */
- area = find_vm_area((void *)spa->kva);
- if (area)
- area->flags &= ~VM_SHAREPOOL;
+ if (!vmalloc_area_clr_flag(spa, spa->kva, VM_SHAREPOOL))
+ pr_warn("share pool: %s: the spa->kva %ld is not valid\n", __func__, spa->kva);
+
+out_drop_area:
__sp_area_drop(spa);
out_unlock:
mutex_unlock(&sp_mutex);
@@ -2162,7 +2219,7 @@ static int sp_unshare_kva(unsigned long kva, unsigned long size)
if (page)
put_page(page);
else
- pr_err("share pool: vmalloc %pK to page/hugepage failed\n",
+ pr_warn("share pool: vmalloc %pK to page/hugepage failed\n",
(void *)addr);
}
--
2.25.1
1
24
From: Mingwang Li <limingwang(a)huawei.com>
euleros inclusion
category: feature
feature: initial KVM RISC-V support
bugzilla: 46845
CVE: NA
This series adds initial KVM RISC-V support. Currently, we are able to
boot Linux on RV64/RV32 Guest with multiple VCPUs.
This series can be found in riscv_kvm_v15 branch at:
https//github.com/avpatel/linux.git
Changes since v1
- follow guileline for submiting patches to openEuler
- add the testing result in this issue
Reference: https://gitee.com/openeuler/kernel/issues/I26X9V
Alistair Francis (1):
Revert "riscv: Use latest system call ABI"
Anup Patel (19):
RISC-V: Add fragmented config for debug options
RISC-V: Enable CPU Hotplug in defconfigs
RISC-V: Add Microchip PolarFire kconfig option
RISC-V: Initial DTS for Microchip ICICLE board
RISC-V: Enable drivers for Microchip PolarFire ICICLE board
RISC-V: Add hypervisor extension related CSR defines
RISC-V: Add initial skeletal KVM support
RISC-V: KVM: Implement VCPU create, init and destroy functions
RISC-V: KVM: Implement VCPU interrupts and requests handling
RISC-V: KVM: Implement KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls
RISC-V: KVM: Implement VCPU world-switch
RISC-V: KVM: Handle MMIO exits for VCPU
RISC-V: KVM: Handle WFI exits for VCPU
RISC-V: KVM: Implement VMID allocator
RISC-V: KVM: Implement stage2 page table programming
RISC-V: KVM: Implement MMU notifiers
RISC-V: KVM: Document RISC-V specific parts of KVM API
RISC-V: KVM: Add MAINTAINERS entry
RISC-V: Enable KVM for RV64 and RV32
Atish Patra (4):
RISC-V: KVM: Add timer functionality
RISC-V: KVM: FP lazy save/restore
RISC-V: KVM: Implement ONE REG interface for FP registers
RISC-V: KVM: Add SBI v0.1 support
Mingwang Li (1):
RISCV: KVM: fix bug in migration
m34782 (1):
Microchip Polarfire SoC Clock Driver
Documentation/virt/kvm/api.rst | 193 +++-
MAINTAINERS | 11 +
arch/riscv/Kconfig | 2 +
arch/riscv/Kconfig.socs | 7 +
arch/riscv/Makefile | 2 +
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/microchip/Makefile | 2 +
.../boot/dts/microchip/icicle-kit-es.dts | 307 +++++
arch/riscv/configs/defconfig | 30 +-
arch/riscv/configs/extra_debug.config | 21 +
arch/riscv/configs/rv32_defconfig | 26 +-
arch/riscv/include/asm/csr.h | 89 ++
arch/riscv/include/asm/kvm_host.h | 278 +++++
arch/riscv/include/asm/kvm_types.h | 7 +
arch/riscv/include/asm/kvm_vcpu_timer.h | 44 +
arch/riscv/include/asm/pgtable-bits.h | 1 +
arch/riscv/include/uapi/asm/kvm.h | 128 +++
arch/riscv/include/uapi/asm/unistd.h | 5 +-
arch/riscv/kernel/asm-offsets.c | 156 +++
arch/riscv/kvm/Kconfig | 36 +
arch/riscv/kvm/Makefile | 15 +
arch/riscv/kvm/main.c | 118 ++
arch/riscv/kvm/mmu.c | 860 ++++++++++++++
arch/riscv/kvm/tlb.S | 74 ++
arch/riscv/kvm/vcpu.c | 1012 +++++++++++++++++
arch/riscv/kvm/vcpu_exit.c | 701 ++++++++++++
arch/riscv/kvm/vcpu_sbi.c | 173 +++
arch/riscv/kvm/vcpu_switch.S | 400 +++++++
arch/riscv/kvm/vcpu_timer.c | 225 ++++
arch/riscv/kvm/vm.c | 81 ++
arch/riscv/kvm/vmid.c | 120 ++
drivers/clk/Kconfig | 5 +
drivers/clk/Makefile | 1 +
drivers/clk/microchip/Makefile | 2 +
drivers/clk/microchip/clk-pfsoc.c | 508 +++++++++
drivers/clocksource/timer-riscv.c | 8 +
include/clocksource/timer-riscv.h | 16 +
include/uapi/linux/kvm.h | 8 +
38 files changed, 5619 insertions(+), 54 deletions(-)
create mode 100644 arch/riscv/boot/dts/microchip/Makefile
create mode 100644 arch/riscv/boot/dts/microchip/icicle-kit-es.dts
create mode 100644 arch/riscv/configs/extra_debug.config
create mode 100644 arch/riscv/include/asm/kvm_host.h
create mode 100644 arch/riscv/include/asm/kvm_types.h
create mode 100644 arch/riscv/include/asm/kvm_vcpu_timer.h
create mode 100644 arch/riscv/include/uapi/asm/kvm.h
create mode 100644 arch/riscv/kvm/Kconfig
create mode 100644 arch/riscv/kvm/Makefile
create mode 100644 arch/riscv/kvm/main.c
create mode 100644 arch/riscv/kvm/mmu.c
create mode 100644 arch/riscv/kvm/tlb.S
create mode 100644 arch/riscv/kvm/vcpu.c
create mode 100644 arch/riscv/kvm/vcpu_exit.c
create mode 100644 arch/riscv/kvm/vcpu_sbi.c
create mode 100644 arch/riscv/kvm/vcpu_switch.S
create mode 100644 arch/riscv/kvm/vcpu_timer.c
create mode 100644 arch/riscv/kvm/vm.c
create mode 100644 arch/riscv/kvm/vmid.c
create mode 100644 drivers/clk/microchip/clk-pfsoc.c
create mode 100644 include/clocksource/timer-riscv.h
--
2.19.1
4
30
22 Dec '20
From: chenjiajun <chenjiajun8(a)huawei.com>
virt inclusion
category: feature
bugzilla: 46853
CVE: NA
Export kvm vcpu info in debugfs entry /sys/kernel/debug/kvm/vcpu_stat,
this entry contains kvm exits and cputime items now. And then, we can get all
kvm vcpu info through this debugfs instead of one entry per kvm exits
items, which will greatly facilitates the collection of performance status.
Currently, only support x86 and aarch64.
--
ChangeList:
v3:
modify kzfree in patches
v2:
modify architecture-dependent st_max to avoid compile err in other arches
v1:
kvm: debugfs: support vcpu_stat debugfs
chenjiajun (4):
kvm: debugfs: Export vcpu stat via debugfs
kvm: debugfs: export remaining aarch64 kvm exit reasons to debugfs
kvm: debugfs: aarch64 export cpu time related items to debugfs
kvm: debugfs: Export x86 kvm exits to vcpu_stat
arch/arm64/include/asm/kvm_host.h | 21 ++++
arch/arm64/kvm/arm.c | 23 +++++
arch/arm64/kvm/guest.c | 33 +++++++
arch/arm64/kvm/handle_exit.c | 8 ++
arch/arm64/kvm/hyp/include/hyp/switch.h | 1 +
arch/arm64/kvm/mmu.c | 1 +
arch/arm64/kvm/sys_regs.c | 11 +++
arch/x86/include/asm/kvm_host.h | 13 +++
arch/x86/kvm/vmx/vmx.c | 10 ++
arch/x86/kvm/x86.c | 70 +++++++++++++
include/linux/kvm_host.h | 19 ++++
virt/kvm/kvm_main.c | 125 ++++++++++++++++++++++++
12 files changed, 335 insertions(+)
--
2.29.GIT
1
4
From: chenjiajun <chenjiajun8(a)huawei.com>
virt inclusion
category: feature
bugzilla: 46853
CVE: NA
Export kvm vcpu info in debugfs entry /sys/kernel/debug/kvm/vcpu_stat,
this entry contains kvm exits and cputime items now. And then, we can get all
kvm vcpu info through this debugfs instead of one entry per kvm exits
items, which will greatly facilitates the collection of performance status.
Currently, only support x86 and aarch64.
--
ChangeList:
v3:
modify kzfree in patches
v2:
modify architecture-dependent st_max to avoid compile err in other arches
v1:
kvm: debugfs: support vcpu_stat debugfs
chenjiajun (4):
kvm: debugfs: Export vcpu stat via debugfs
kvm: debugfs: export remaining aarch64 kvm exit reasons to debugfs
kvm: debugfs: aarch64 export cpu time related items to debugfs
kvm: debugfs: Export x86 kvm exits to vcpu_stat
arch/arm64/include/asm/kvm_host.h | 21 ++++
arch/arm64/kvm/arm.c | 23 +++++
arch/arm64/kvm/guest.c | 33 +++++++
arch/arm64/kvm/handle_exit.c | 8 ++
arch/arm64/kvm/hyp/include/hyp/switch.h | 1 +
arch/arm64/kvm/mmu.c | 1 +
arch/arm64/kvm/sys_regs.c | 11 +++
arch/x86/include/asm/kvm_host.h | 13 +++
arch/x86/kvm/vmx/vmx.c | 10 ++
arch/x86/kvm/x86.c | 70 +++++++++++++
include/linux/kvm_host.h | 19 ++++
virt/kvm/kvm_main.c | 125 ++++++++++++++++++++++++
12 files changed, 335 insertions(+)
--
2.29.GIT
2
5
*** BLURB HERE ***
Yang Yingliang (3):
irqchip/mbigen: rename register marcros
irqchip/mbigen: add support for a MBIGEN generating SPIs
dt-bindings/irqchip/mbigen: add example of MBIGEN generate SPIs
.../hisilicon,mbigen-v2.txt | 17 +++++++-
drivers/irqchip/irq-mbigen.c | 39 +++++++++++++------
2 files changed, 44 insertions(+), 12 deletions(-)
--
2.25.0
2
4
From: chenjiajun <chenjiajun8(a)huawei.com>
virt inclusion
category: feature
bugzilla: 46853
CVE: NA
Export kvm vcpu info in debugfs entry /sys/kernel/debug/kvm/vcpu_stat,
this entry contains kvm exits and cputime items now. And then, we can get all
kvm vcpu info through this debugfs instead of one entry per kvm exits
items, which will greatly facilitates the collection of performance status.
Currently, only support x86 and aarch64.
--
ChangeList:
v2:
modify architecture-dependent st_max to avoid compile err in other arches
v1:
kvm: debugfs: support vcpu_stat debugfs
chenjiajun (4):
kvm: debugfs: Export vcpu stat via debugfs
kvm: debugfs: export remaining aarch64 kvm exit reasons to debugfs
kvm: debugfs: aarch64 export cpu time related items to debugfs
kvm: debugfs: Export x86 kvm exits to vcpu_stat
arch/arm64/include/asm/kvm_host.h | 21 ++++
arch/arm64/kvm/arm.c | 23 +++++
arch/arm64/kvm/guest.c | 33 +++++++
arch/arm64/kvm/handle_exit.c | 8 ++
arch/arm64/kvm/hyp/include/hyp/switch.h | 1 +
arch/arm64/kvm/mmu.c | 1 +
arch/arm64/kvm/sys_regs.c | 11 +++
arch/x86/include/asm/kvm_host.h | 13 +++
arch/x86/kvm/vmx/vmx.c | 10 ++
arch/x86/kvm/x86.c | 70 +++++++++++++
include/linux/kvm_host.h | 19 ++++
virt/kvm/kvm_main.c | 124 ++++++++++++++++++++++++
12 files changed, 334 insertions(+)
--
2.29.GIT
1
4
[PATCH OLK-5.10 1/1] PCI: Add MCFG quirks for some Hisilicon Chip host controllers
by Chen Jun 22 Dec '20
by Chen Jun 22 Dec '20
22 Dec '20
From: Xiongfeng Wang <wangxiongfeng2(a)huawei.com>
euler inclusion
category: bugfix
bugzilla: 46851
CVE: NA
-------------------------------------------------
The PCIe controller in some Hisilicon Chip is not completely ECAM-compliant.
Part of its PCIe cores do not support ECAM.
Signed-off-by: Xiongfeng Wang <wangxiongfeng2(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: yangerkun <yangerkun(a)huawei.com>
---
drivers/acpi/pci_mcfg.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
index 95f23acd5b80..3f310cfc9e7d 100644
--- a/drivers/acpi/pci_mcfg.c
+++ b/drivers/acpi/pci_mcfg.c
@@ -77,6 +77,10 @@ static struct mcfg_fixup mcfg_quirks[] = {
HISI_QUAD_DOM("HIP07 ", 4, &hisi_pcie_ops),
HISI_QUAD_DOM("HIP07 ", 8, &hisi_pcie_ops),
HISI_QUAD_DOM("HIP07 ", 12, &hisi_pcie_ops),
+ HISI_QUAD_DOM("HIP12 ", 0x20, &hisi_pcie_ops),
+ HISI_QUAD_DOM("HIP12 ", 0x24, &hisi_pcie_ops),
+ HISI_QUAD_DOM("HIP12 ", 0x28, &hisi_pcie_ops),
+ HISI_QUAD_DOM("HIP12 ", 0x2c, &hisi_pcie_ops),
#define THUNDER_PEM_RES(addr, node) \
DEFINE_RES_MEM((addr) + ((u64) (node) << 44), 0x39 * SZ_16M)
--
2.25.0
1
0
*** BLURB HERE ***
Hanjun Guo (2):
arm64: cache: Add flush_dcache_area() for module use
arm64: cache: Export and add cache invalidation and clean ABIs for
module use
arch/arm64/include/asm/cacheflush.h | 51 +++++++++++++++++++++++++++++
arch/arm64/mm/flush.c | 3 ++
2 files changed, 54 insertions(+)
--
2.25.0
1
2
22 Dec '20
From: Xiangyu Lu <luxiangyu(a)huawei.com>
euler inclusion
category: bugfix
bugzilla: 46850
CVE: NA
---------------------------------
Linux kernel allow to specify a single-user mode, or specify the init process by
init parameter, which could bypass the login authentication mechanisms, direct
access to root identify. Close init kernel boot parameters through
CONFIG_SECURITY_BOOT_INIT.
Signed-off-by: Xiangyu Lu <luxiangyu(a)huawei.com>
Reviewed-by: Wang Kai <morgan.wang(a)huawei.com>
Signed-off-by: Weilong Chen <chenweilong(a)huawei.com>
[hj: backport from hulk-3.10 for security enhancement]
Signed-off-by: Hanjun Guo <hanjun.guo(a)linaro.org>
Signed-off-by: gaobo <gaobo794(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: zhangyi (F) <yi.zhang(a)huawei.com>
---
init/main.c | 2 ++
security/Kconfig | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/init/main.c b/init/main.c
index 32b2a8affafd..1e3c3371ea5d 100644
--- a/init/main.c
+++ b/init/main.c
@@ -572,6 +572,7 @@ static int __init unknown_bootoption(char *param, char *val,
return 0;
}
+#ifndef CONFIG_SECURITY_BOOT_INIT
static int __init init_setup(char *str)
{
unsigned int i;
@@ -600,6 +601,7 @@ static int __init rdinit_setup(char *str)
return 1;
}
__setup("rdinit=", rdinit_setup);
+#endif
#ifndef CONFIG_SMP
static const unsigned int setup_max_cpus = NR_CPUS;
diff --git a/security/Kconfig b/security/Kconfig
index 7561f6f99f1d..a178816f61ed 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -291,5 +291,11 @@ config LSM
source "security/Kconfig.hardening"
+config SECURITY_BOOT_INIT
+ bool "Disable init & rdinit parameters in cmdline"
+ default n
+ help
+ No support init and rdinit parameters in cmdline
+
endmenu
--
2.25.0
1
0
[PATCH OLK-5.10 0/2] config: add initial openeuler_defconfig for arm64 & x86
by Xie XiuQi 21 Dec '20
by Xie XiuQi 21 Dec '20
21 Dec '20
Add initial configs for arm64 & x86 platform.
Use openEuler-20.03's config as base, re-generate it on 5.10 kernel.
The major changes:
- use 52 bit VA & PA
- enable CONFIG_PSI
- support more kunpeng drivers on arm64
Xie XiuQi (2):
config: add initial openeuler_defconfig for arm64
config: add initial openeuler_defconfig for x86
arch/arm64/configs/openeuler_defconfig | 7068 ++++++++++++++++++++
arch/x86/configs/openeuler_defconfig | 8271 ++++++++++++++++++++++++
2 files changed, 15339 insertions(+)
create mode 100644 arch/arm64/configs/openeuler_defconfig
create mode 100644 arch/x86/configs/openeuler_defconfig
--
2.20.1
1
2
21 Dec '20
From: Linxu Fang <fanglinxu(a)huawei.com>
maillist inclusion
category: feature
bugzilla: 46792
CVE: NA
Reference: https://lists.linaro.org/pipermail/linaro-kernel/2013-October/008031.html
----------------------------------------
It's a improved version of Steve Capper's RFC patch, see:
https://lists.linaro.org/pipermail/linaro-kernel/2013-October/008031.html
Signed-off-by: Linxu Fang <fanglinxu(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm/Kconfig | 2 +-
arch/arm/include/asm/hugetlb-2level.h | 148 +++++++++++++++++++
arch/arm/include/asm/hugetlb.h | 6 +-
arch/arm/include/asm/pgtable-2level-hwdef.h | 2 +
arch/arm/include/asm/pgtable-2level.h | 154 +++++++++++++++++++-
arch/arm/include/asm/pgtable-3level.h | 2 +-
arch/arm/include/asm/pgtable.h | 14 ++
arch/arm/kernel/head.S | 4 +
arch/arm/mm/fault.c | 26 ++--
arch/arm/mm/fsr-2level.c | 4 +-
arch/arm/mm/hugetlbpage.c | 2 +-
arch/arm/mm/mmu.c | 25 ++++
12 files changed, 369 insertions(+), 20 deletions(-)
create mode 100644 arch/arm/include/asm/hugetlb-2level.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 002e0cf025f5..3efce886d7a0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1545,7 +1545,7 @@ config HW_PERF_EVENTS
config SYS_SUPPORTS_HUGETLBFS
def_bool y
- depends on ARM_LPAE
+ depends on ARM_LPAE || (!CPU_USE_DOMAINS && !MEMORY_FAILURE && !CPU_SW_DOMAIN_PAN)
config HAVE_ARCH_TRANSPARENT_HUGEPAGE
def_bool y
diff --git a/arch/arm/include/asm/hugetlb-2level.h b/arch/arm/include/asm/hugetlb-2level.h
new file mode 100644
index 000000000000..ce746dae2497
--- /dev/null
+++ b/arch/arm/include/asm/hugetlb-2level.h
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/include/asm/hugetlb-2level.h
+ *
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ASM_ARM_HUGETLB_2LEVEL_H
+#define _ASM_ARM_HUGETLB_2LEVEL_H
+
+#define __HAVE_ARCH_HUGE_PTEP_GET
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ pmd_t pmd = *((pmd_t *)ptep);
+ pte_t retval;
+
+ if (!pmd_val(pmd))
+ return __pte(0);
+
+ retval = __pte((pteval_t) (pmd_val(pmd) & HPAGE_MASK)
+ | arm_hugepteprotval);
+
+ if (pmd_exec(pmd))
+ retval = pte_mkexec(retval);
+ else
+ retval = pte_mknexec(retval);
+
+ if (pmd_young(pmd))
+ retval = pte_mkyoung(retval);
+ else
+ retval = pte_mkold(retval);
+
+ if (pmd_dirty(pmd))
+ retval = pte_mkdirty(retval);
+ else
+ retval = pte_mkclean(retval);
+
+ if (pmd_write(pmd))
+ retval = pte_mkwrite(retval);
+ else
+ retval = pte_wrprotect(retval);
+
+ if (pmd & PMD_SECT_BUFFERABLE)
+ retval |= PMD_SECT_BUFFERABLE;
+ else
+ retval &= ~PMD_SECT_BUFFERABLE;
+
+ if (pmd & PMD_SECT_CACHEABLE)
+ retval |= PMD_SECT_CACHEABLE;
+ else
+ retval &= ~PMD_SECT_CACHEABLE;
+
+ if (pmd & PMD_SECT_TEX(1))
+ retval |= L_PTE_MT_DEV_SHARED;
+ else
+ retval &= ~L_PTE_MT_DEV_SHARED;
+
+ if (pmd & PMD_SECT_S)
+ retval |= L_PTE_SHARED;
+ else
+ retval &= ~(L_PTE_SHARED);
+
+ if (pmd_protnone(pmd))
+ retval = pte_mkprotnone(retval);
+ else
+ retval = pte_rmprotnone(retval);
+
+ return retval;
+}
+
+#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ pmdval_t pmdval = (pmdval_t) pte_val(pte);
+ pmd_t *pmdp = (pmd_t *) ptep;
+
+ /* take the target address bits from the pte only */
+ pmdval &= HPAGE_MASK;
+
+ /*
+ * now use pmd_modify to translate the permission bits from the pte
+ * and set the memory type information.
+ */
+ pmdval = pmd_val(pmd_modify(__pmd(pmdval), __pgprot(pte_val(pte))));
+
+ __sync_icache_dcache(pte);
+
+ set_pmd_at(mm, addr, pmdp, __pmd(pmdval));
+}
+
+static inline pte_t pte_mkhuge(pte_t pte) { return pte; }
+
+#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *)ptep;
+
+ pmd_clear(pmdp);
+ flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *) ptep;
+
+ set_pmd_at(mm, addr, pmdp, pmd_wrprotect(*pmdp));
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *)ptep;
+ pte_t pte = huge_ptep_get(ptep);
+
+ pmd_clear(pmdp);
+
+ return pte;
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ int changed = !pte_same(huge_ptep_get(ptep), pte);
+
+ if (changed) {
+ set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+ flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+ }
+
+ return changed;
+}
+
+#endif /* _ASM_ARM_HUGETLB_2LEVEL_H */
diff --git a/arch/arm/include/asm/hugetlb.h b/arch/arm/include/asm/hugetlb.h
index d02d6ca88e92..44fd1a5f3a32 100644
--- a/arch/arm/include/asm/hugetlb.h
+++ b/arch/arm/include/asm/hugetlb.h
@@ -11,7 +11,11 @@
#define _ASM_ARM_HUGETLB_H
#include <asm/page.h>
-#include <asm/hugetlb-3level.h>
+#ifdef CONFIG_ARM_LPAE
+ #include <asm/hugetlb-3level.h>
+#else
+#include <asm/hugetlb-2level.h>
+#endif
#include <asm-generic/hugetlb.h>
static inline void arch_clear_hugepage_flags(struct page *page)
diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h
index 556937e1790e..b3ea5d00b5c7 100644
--- a/arch/arm/include/asm/pgtable-2level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
@@ -20,7 +20,9 @@
#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */
#define PMD_BIT4 (_AT(pmdval_t, 1) << 4)
#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5)
+#ifndef PMD_DOMAIN_MASK
#define PMD_DOMAIN_MASK PMD_DOMAIN(0x0f)
+#endif
#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */
/*
* - section
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index baf7d0204eb5..000feaf88248 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -7,6 +7,8 @@
#ifndef _ASM_PGTABLE_2LEVEL_H
#define _ASM_PGTABLE_2LEVEL_H
+#include <asm/tlbflush.h>
+
#define __PAGETABLE_PMD_FOLDED 1
/*
@@ -185,13 +187,27 @@
#define pud_clear(pudp) do { } while (0)
#define set_pud(pud,pudp) do { } while (0)
+static inline int pmd_large(pmd_t pmd)
+{
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_FAULT)
+ return pmd_val(pmd);
+
+ return ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT);
+}
+
+static inline int pte_huge(pte_t pte)
+{
+ pmd_t pmd = (pmd_t)pte;
+
+ return pmd_large(pmd);
+}
+
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
{
return (pmd_t *)pud;
}
#define pmd_offset pmd_offset
-#define pmd_large(pmd) (pmd_val(pmd) & 2)
#define pmd_leaf(pmd) (pmd_val(pmd) & 2)
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
#define pmd_present(pmd) (pmd_val(pmd))
@@ -215,6 +231,142 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+/*
+ * now follows some of the definitions to allow huge page support, we can't put
+ * these in the hugetlb source files as they are also required for transparent
+ * hugepage support.
+ */
+
+#define HPAGE_SHIFT PMD_SHIFT
+#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
+#define HUGE_LINUX_PTE_COUNT (PAGE_OFFSET >> HPAGE_SHIFT)
+#define HUGE_LINUX_PTE_SIZE (HUGE_LINUX_PTE_COUNT * sizeof(pte_t *))
+#define HUGE_LINUX_PTE_INDEX(addr) (addr >> HPAGE_SHIFT)
+
+/*
+ * We re-purpose the following domain bits in the section descriptor
+ */
+#ifndef PMD_DOMAIN_MASK
+#define PMD_DOMAIN_MASK (_AT(pmdval_t, 0xF) << 5)
+#endif
+#define PMD_DSECT_PROT_NONE (_AT(pmdval_t, 1) << 5)
+#define PMD_DSECT_DIRTY (_AT(pmdval_t, 1) << 6)
+#define PMD_DSECT_AF (_AT(pmdval_t, 1) << 7)
+
+#define PMD_BIT_FUNC(fn, op) \
+static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+
+extern pmdval_t arm_hugepmdprotval;
+extern pteval_t arm_hugepteprotval;
+
+#define pmd_mkhuge(pmd) (__pmd((pmd_val(pmd) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT))
+
+PMD_BIT_FUNC(mkold, &= ~PMD_DSECT_AF);
+PMD_BIT_FUNC(mkdirty, |= PMD_DSECT_DIRTY);
+PMD_BIT_FUNC(mkclean, &= ~PMD_DSECT_DIRTY);
+PMD_BIT_FUNC(mkyoung, |= PMD_DSECT_AF);
+PMD_BIT_FUNC(mkwrite, |= PMD_SECT_AP_WRITE);
+PMD_BIT_FUNC(wrprotect, &= ~PMD_SECT_AP_WRITE);
+PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+PMD_BIT_FUNC(mkexec, &= ~PMD_SECT_XN);
+PMD_BIT_FUNC(mknexec, |= PMD_SECT_XN);
+PMD_BIT_FUNC(mkprotnone, |= PMD_DSECT_PROT_NONE);
+PMD_BIT_FUNC(rmprotnone, &= ~PMD_DSECT_PROT_NONE);
+
+#ifdef CONFIG_NUMA_BALANCING
+#define pmd_protnone(pmd) (pmd_val(pmd) & PMD_DSECT_PROT_NONE)
+#else
+static inline int pmd_protnone(pmd_t pmd);
+#endif
+#define pmd_young(pmd) (pmd_val(pmd) & PMD_DSECT_AF)
+#define pmd_write(pmd) (pmd_val(pmd) & PMD_SECT_AP_WRITE)
+#define pmd_exec(pmd) (!(pmd_val(pmd) & PMD_SECT_XN))
+#define pmd_dirty(pmd) (pmd_val(pmd) & PMD_DSECT_DIRTY)
+
+#define __HAVE_ARCH_PMD_WRITE
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ /*
+ * we can sometimes be passed a pmd pointing to a level 2 descriptor
+ * from collapse_huge_page.
+ */
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) {
+ pmdp[0] = __pmd(pmd_val(pmd));
+ pmdp[1] = __pmd(pmd_val(pmd) + 256 * sizeof(pte_t));
+ } else {
+ if (pmd_protnone(pmd))
+ pmd_val(pmd) &= ~PMD_TYPE_MASK;
+ else
+ pmd_val(pmd) |= PMD_TYPE_SECT;
+
+ pmdp[0] = __pmd(pmd_val(pmd));
+ pmdp[1] = __pmd(pmd_val(pmd) + SECTION_SIZE);
+ }
+
+ flush_pmd_entry(pmdp);
+}
+
+#define pmd_modify(pmd, prot) \
+({ \
+ pmd_t pmdret = __pmd((pmd_val(pmd) \
+ & (PMD_MASK | PMD_DOMAIN_MASK)) \
+ | arm_hugepmdprotval); \
+ pgprot_t inprot = prot; \
+ pte_t newprot = __pte(pgprot_val(inprot)); \
+ \
+ if (pte_dirty(newprot)) \
+ pmdret = pmd_mkdirty(pmdret); \
+ else \
+ pmdret = pmd_mkclean(pmdret); \
+ \
+ if (pte_exec(newprot)) \
+ pmdret = pmd_mkexec(pmdret); \
+ else \
+ pmdret = pmd_mknexec(pmdret); \
+ \
+ if (pte_write(newprot)) \
+ pmdret = pmd_mkwrite(pmdret); \
+ else \
+ pmdret = pmd_wrprotect(pmdret); \
+ \
+ if (pte_young(newprot)) \
+ pmdret = pmd_mkyoung(pmdret); \
+ else \
+ pmdret = pmd_mkold(pmdret); \
+ \
+ if (pte_protnone(newprot)) \
+ pmdret = pmd_mkprotnone(pmdret); \
+ else \
+ pmdret = pmd_rmprotnone(pmdret); \
+ \
+ if (pte_val(newprot) & PMD_SECT_BUFFERABLE) \
+ pmdret |= PMD_SECT_BUFFERABLE; \
+ else \
+ pmdret &= ~PMD_SECT_BUFFERABLE; \
+ \
+ if (pte_val(newprot) & PMD_SECT_CACHEABLE) \
+ pmdret |= PMD_SECT_CACHEABLE; \
+ else \
+ pmdret &= ~PMD_SECT_CACHEABLE; \
+ \
+ if (pte_val(newprot) & L_PTE_MT_DEV_SHARED) \
+ pmdret |= PMD_SECT_TEX(1); \
+ else \
+ pmdret &= ~(PMD_SECT_TEX(1)); \
+ \
+ if (pte_val(newprot) & L_PTE_SHARED) \
+ pmdret |= PMD_SECT_S; \
+ else \
+ pmdret &= ~PMD_SECT_S; \
+ \
+ pmdret; \
+})
+
/*
* We don't have huge page support for short descriptors, for the moment
* define empty stubs for use by pin_page_for_write.
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 2b85d175e999..af53b40d1627 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -55,7 +55,7 @@
* Hugetlb definitions.
*/
#define HPAGE_SHIFT PMD_SHIFT
-#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_SIZE (_AC(1, ULL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index c02f24400369..e3a6ebcfe415 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -196,6 +196,10 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_young(pte) (pte_isset((pte), L_PTE_YOUNG))
#define pte_exec(pte) (pte_isclear((pte), L_PTE_XN))
+#ifdef CONFIG_NUMA_BALANCING
+#define pte_protnone(pte) (pte_val(pte) & L_PTE_NONE)
+#endif
+
#define pte_valid_user(pte) \
(pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte))
@@ -274,6 +278,16 @@ static inline pte_t pte_mknexec(pte_t pte)
return set_pte_bit(pte, __pgprot(L_PTE_XN));
}
+static inline pte_t pte_mkprotnone(pte_t pte)
+{
+ return set_pte_bit(pte, __pgprot(L_PTE_NONE));
+}
+
+static inline pte_t pte_rmprotnone(pte_t pte)
+{
+ return clear_pte_bit(pte, __pgprot(L_PTE_NONE));
+}
+
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index f8904227e7fd..dfc95659bb89 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -460,8 +460,12 @@ __enable_mmu:
#endif
#ifdef CONFIG_ARM_LPAE
mcrr p15, 0, r4, r5, c2 @ load TTBR0
+#else
+#ifdef CONFIG_SYS_SUPPORTS_HUGETLBFS
+ ldr r5, =0x55555555
#else
mov r5, #DACR_INIT
+#endif
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
#endif
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index efa402025031..9985bab5ee66 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -26,6 +26,10 @@
#ifdef CONFIG_MMU
+#if defined(CONFIG_SYS_SUPPORTS_HUGETLBFS) && !defined(CONFIG_ARM_LPAE)
+#include <linux/hugetlb.h>
+#endif
+
/*
* This is useful to dump out the page tables associated with
* 'addr' in mm 'mm'.
@@ -76,6 +80,15 @@ void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr)
break;
if (pmd_bad(*pmd)) {
+#if !defined(CONFIG_ARM_LPAE) && defined(CONFIG_HUGETLBFS)
+ if (pte_huge((pte_t)*pgd)) {
+ pte_t huge_pte = huge_ptep_get((pte_t *)pgd);
+
+ pr_alert("[%08lx] *ppgd=%08llx", addr,
+ (long long)pmd_val(huge_pte));
+ break;
+ }
+#endif
pr_cont("(bad)");
break;
}
@@ -462,19 +475,6 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
}
#endif /* CONFIG_MMU */
-/*
- * Some section permission faults need to be handled gracefully.
- * They can happen due to a __{get,put}_user during an oops.
- */
-#ifndef CONFIG_ARM_LPAE
-static int
-do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- do_bad_area(addr, fsr, regs);
- return 0;
-}
-#endif /* CONFIG_ARM_LPAE */
-
/*
* This abort handler always returns "fault".
*/
diff --git a/arch/arm/mm/fsr-2level.c b/arch/arm/mm/fsr-2level.c
index f2be95197265..f22e33ab0dc6 100644
--- a/arch/arm/mm/fsr-2level.c
+++ b/arch/arm/mm/fsr-2level.c
@@ -17,7 +17,7 @@ static struct fsr_info fsr_info[] = {
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
- { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
/*
@@ -57,7 +57,7 @@ static struct fsr_info ifsr_info[] = {
{ do_bad, SIGBUS, 0, "unknown 10" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
- { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
{ do_bad, SIGBUS, 0, "unknown 16" },
diff --git a/arch/arm/mm/hugetlbpage.c b/arch/arm/mm/hugetlbpage.c
index dd7a0277c5c0..5ede7ef5e531 100644
--- a/arch/arm/mm/hugetlbpage.c
+++ b/arch/arm/mm/hugetlbpage.c
@@ -30,5 +30,5 @@ int pud_huge(pud_t pud)
int pmd_huge(pmd_t pmd)
{
- return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT);
+ return pmd_large(pmd);
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index ab69250a86bc..911ce69f04a0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -402,6 +402,20 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
}
+/*
+ * If the system supports huge pages and we are running with short descriptors,
+ * then compute the pmd and linux pte prot values for a huge page.
+ *
+ * These values are used by both the HugeTLB and THP code.
+ */
+#if defined(CONFIG_SYS_SUPPORTS_HUGETLBFS) && !defined(CONFIG_ARM_LPAE)
+pmdval_t arm_hugepmdprotval;
+EXPORT_SYMBOL(arm_hugepmdprotval);
+
+pteval_t arm_hugepteprotval;
+EXPORT_SYMBOL(arm_hugepteprotval);
+#endif
+
/*
* Adjust the PMD section entries according to the CPU in use.
*/
@@ -667,6 +681,17 @@ static void __init build_mem_type_table(void)
if (t->prot_sect)
t->prot_sect |= PMD_DOMAIN(t->domain);
}
+
+#if defined(CONFIG_SYS_SUPPORTS_HUGETLBFS) && !defined(CONFIG_ARM_LPAE)
+ /*
+ * we assume all huge pages are user pages and that hardware access
+ * flag updates are disabled (i.e. SCTLR.AFE == 0b).
+ */
+ arm_hugepteprotval = mem_types[MT_MEMORY_RWX].prot_pte | L_PTE_USER | L_PTE_VALID;
+
+ arm_hugepmdprotval = mem_types[MT_MEMORY_RWX].prot_sect | PMD_SECT_AP_READ
+ | PMD_SECT_nG;
+#endif
}
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
--
2.25.0
2
1
21 Dec '20
From: f00440829 <fanglinxu(a)huawei.com>
euler inclusion
category: feature
bugzilla: 46792
CVE: NA
----------------------------------------
It's a improved version of Steve Capper's RFC patch, see:
https://lists.linaro.org/pipermail/linaro-kernel/2013-October/008031.html
Signed-off-by: Linxu Fang <fanglinxu(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
Signed-off-by: Chen Jun <chenjun102(a)huawei.com>
---
arch/arm/Kconfig | 2 +-
arch/arm/include/asm/hugetlb-2level.h | 148 +++++++++++++++++++
arch/arm/include/asm/hugetlb.h | 6 +-
arch/arm/include/asm/pgtable-2level-hwdef.h | 2 +
arch/arm/include/asm/pgtable-2level.h | 154 +++++++++++++++++++-
arch/arm/include/asm/pgtable-3level.h | 2 +-
arch/arm/include/asm/pgtable.h | 14 ++
arch/arm/kernel/head.S | 4 +
arch/arm/mm/fault.c | 26 ++--
arch/arm/mm/fsr-2level.c | 4 +-
arch/arm/mm/hugetlbpage.c | 2 +-
arch/arm/mm/mmu.c | 25 ++++
12 files changed, 369 insertions(+), 20 deletions(-)
create mode 100644 arch/arm/include/asm/hugetlb-2level.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 002e0cf025f5..3efce886d7a0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1545,7 +1545,7 @@ config HW_PERF_EVENTS
config SYS_SUPPORTS_HUGETLBFS
def_bool y
- depends on ARM_LPAE
+ depends on ARM_LPAE || (!CPU_USE_DOMAINS && !MEMORY_FAILURE && !CPU_SW_DOMAIN_PAN)
config HAVE_ARCH_TRANSPARENT_HUGEPAGE
def_bool y
diff --git a/arch/arm/include/asm/hugetlb-2level.h b/arch/arm/include/asm/hugetlb-2level.h
new file mode 100644
index 000000000000..ce746dae2497
--- /dev/null
+++ b/arch/arm/include/asm/hugetlb-2level.h
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/include/asm/hugetlb-2level.h
+ *
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ASM_ARM_HUGETLB_2LEVEL_H
+#define _ASM_ARM_HUGETLB_2LEVEL_H
+
+#define __HAVE_ARCH_HUGE_PTEP_GET
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ pmd_t pmd = *((pmd_t *)ptep);
+ pte_t retval;
+
+ if (!pmd_val(pmd))
+ return __pte(0);
+
+ retval = __pte((pteval_t) (pmd_val(pmd) & HPAGE_MASK)
+ | arm_hugepteprotval);
+
+ if (pmd_exec(pmd))
+ retval = pte_mkexec(retval);
+ else
+ retval = pte_mknexec(retval);
+
+ if (pmd_young(pmd))
+ retval = pte_mkyoung(retval);
+ else
+ retval = pte_mkold(retval);
+
+ if (pmd_dirty(pmd))
+ retval = pte_mkdirty(retval);
+ else
+ retval = pte_mkclean(retval);
+
+ if (pmd_write(pmd))
+ retval = pte_mkwrite(retval);
+ else
+ retval = pte_wrprotect(retval);
+
+ if (pmd & PMD_SECT_BUFFERABLE)
+ retval |= PMD_SECT_BUFFERABLE;
+ else
+ retval &= ~PMD_SECT_BUFFERABLE;
+
+ if (pmd & PMD_SECT_CACHEABLE)
+ retval |= PMD_SECT_CACHEABLE;
+ else
+ retval &= ~PMD_SECT_CACHEABLE;
+
+ if (pmd & PMD_SECT_TEX(1))
+ retval |= L_PTE_MT_DEV_SHARED;
+ else
+ retval &= ~L_PTE_MT_DEV_SHARED;
+
+ if (pmd & PMD_SECT_S)
+ retval |= L_PTE_SHARED;
+ else
+ retval &= ~(L_PTE_SHARED);
+
+ if (pmd_protnone(pmd))
+ retval = pte_mkprotnone(retval);
+ else
+ retval = pte_rmprotnone(retval);
+
+ return retval;
+}
+
+#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ pmdval_t pmdval = (pmdval_t) pte_val(pte);
+ pmd_t *pmdp = (pmd_t *) ptep;
+
+ /* take the target address bits from the pte only */
+ pmdval &= HPAGE_MASK;
+
+ /*
+ * now use pmd_modify to translate the permission bits from the pte
+ * and set the memory type information.
+ */
+ pmdval = pmd_val(pmd_modify(__pmd(pmdval), __pgprot(pte_val(pte))));
+
+ __sync_icache_dcache(pte);
+
+ set_pmd_at(mm, addr, pmdp, __pmd(pmdval));
+}
+
+static inline pte_t pte_mkhuge(pte_t pte) { return pte; }
+
+#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *)ptep;
+
+ pmd_clear(pmdp);
+ flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *) ptep;
+
+ set_pmd_at(mm, addr, pmdp, pmd_wrprotect(*pmdp));
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *)ptep;
+ pte_t pte = huge_ptep_get(ptep);
+
+ pmd_clear(pmdp);
+
+ return pte;
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ int changed = !pte_same(huge_ptep_get(ptep), pte);
+
+ if (changed) {
+ set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+ flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+ }
+
+ return changed;
+}
+
+#endif /* _ASM_ARM_HUGETLB_2LEVEL_H */
diff --git a/arch/arm/include/asm/hugetlb.h b/arch/arm/include/asm/hugetlb.h
index d02d6ca88e92..44fd1a5f3a32 100644
--- a/arch/arm/include/asm/hugetlb.h
+++ b/arch/arm/include/asm/hugetlb.h
@@ -11,7 +11,11 @@
#define _ASM_ARM_HUGETLB_H
#include <asm/page.h>
-#include <asm/hugetlb-3level.h>
+#ifdef CONFIG_ARM_LPAE
+ #include <asm/hugetlb-3level.h>
+#else
+#include <asm/hugetlb-2level.h>
+#endif
#include <asm-generic/hugetlb.h>
static inline void arch_clear_hugepage_flags(struct page *page)
diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h
index 556937e1790e..b3ea5d00b5c7 100644
--- a/arch/arm/include/asm/pgtable-2level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
@@ -20,7 +20,9 @@
#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */
#define PMD_BIT4 (_AT(pmdval_t, 1) << 4)
#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5)
+#ifndef PMD_DOMAIN_MASK
#define PMD_DOMAIN_MASK PMD_DOMAIN(0x0f)
+#endif
#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */
/*
* - section
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index baf7d0204eb5..000feaf88248 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -7,6 +7,8 @@
#ifndef _ASM_PGTABLE_2LEVEL_H
#define _ASM_PGTABLE_2LEVEL_H
+#include <asm/tlbflush.h>
+
#define __PAGETABLE_PMD_FOLDED 1
/*
@@ -185,13 +187,27 @@
#define pud_clear(pudp) do { } while (0)
#define set_pud(pud,pudp) do { } while (0)
+static inline int pmd_large(pmd_t pmd)
+{
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_FAULT)
+ return pmd_val(pmd);
+
+ return ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT);
+}
+
+static inline int pte_huge(pte_t pte)
+{
+ pmd_t pmd = (pmd_t)pte;
+
+ return pmd_large(pmd);
+}
+
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
{
return (pmd_t *)pud;
}
#define pmd_offset pmd_offset
-#define pmd_large(pmd) (pmd_val(pmd) & 2)
#define pmd_leaf(pmd) (pmd_val(pmd) & 2)
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
#define pmd_present(pmd) (pmd_val(pmd))
@@ -215,6 +231,142 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+/*
+ * now follows some of the definitions to allow huge page support, we can't put
+ * these in the hugetlb source files as they are also required for transparent
+ * hugepage support.
+ */
+
+#define HPAGE_SHIFT PMD_SHIFT
+#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
+#define HUGE_LINUX_PTE_COUNT (PAGE_OFFSET >> HPAGE_SHIFT)
+#define HUGE_LINUX_PTE_SIZE (HUGE_LINUX_PTE_COUNT * sizeof(pte_t *))
+#define HUGE_LINUX_PTE_INDEX(addr) (addr >> HPAGE_SHIFT)
+
+/*
+ * We re-purpose the following domain bits in the section descriptor
+ */
+#ifndef PMD_DOMAIN_MASK
+#define PMD_DOMAIN_MASK (_AT(pmdval_t, 0xF) << 5)
+#endif
+#define PMD_DSECT_PROT_NONE (_AT(pmdval_t, 1) << 5)
+#define PMD_DSECT_DIRTY (_AT(pmdval_t, 1) << 6)
+#define PMD_DSECT_AF (_AT(pmdval_t, 1) << 7)
+
+#define PMD_BIT_FUNC(fn, op) \
+static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+
+extern pmdval_t arm_hugepmdprotval;
+extern pteval_t arm_hugepteprotval;
+
+#define pmd_mkhuge(pmd) (__pmd((pmd_val(pmd) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT))
+
+PMD_BIT_FUNC(mkold, &= ~PMD_DSECT_AF);
+PMD_BIT_FUNC(mkdirty, |= PMD_DSECT_DIRTY);
+PMD_BIT_FUNC(mkclean, &= ~PMD_DSECT_DIRTY);
+PMD_BIT_FUNC(mkyoung, |= PMD_DSECT_AF);
+PMD_BIT_FUNC(mkwrite, |= PMD_SECT_AP_WRITE);
+PMD_BIT_FUNC(wrprotect, &= ~PMD_SECT_AP_WRITE);
+PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+PMD_BIT_FUNC(mkexec, &= ~PMD_SECT_XN);
+PMD_BIT_FUNC(mknexec, |= PMD_SECT_XN);
+PMD_BIT_FUNC(mkprotnone, |= PMD_DSECT_PROT_NONE);
+PMD_BIT_FUNC(rmprotnone, &= ~PMD_DSECT_PROT_NONE);
+
+#ifdef CONFIG_NUMA_BALANCING
+#define pmd_protnone(pmd) (pmd_val(pmd) & PMD_DSECT_PROT_NONE)
+#else
+static inline int pmd_protnone(pmd_t pmd);
+#endif
+#define pmd_young(pmd) (pmd_val(pmd) & PMD_DSECT_AF)
+#define pmd_write(pmd) (pmd_val(pmd) & PMD_SECT_AP_WRITE)
+#define pmd_exec(pmd) (!(pmd_val(pmd) & PMD_SECT_XN))
+#define pmd_dirty(pmd) (pmd_val(pmd) & PMD_DSECT_DIRTY)
+
+#define __HAVE_ARCH_PMD_WRITE
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ /*
+ * we can sometimes be passed a pmd pointing to a level 2 descriptor
+ * from collapse_huge_page.
+ */
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) {
+ pmdp[0] = __pmd(pmd_val(pmd));
+ pmdp[1] = __pmd(pmd_val(pmd) + 256 * sizeof(pte_t));
+ } else {
+ if (pmd_protnone(pmd))
+ pmd_val(pmd) &= ~PMD_TYPE_MASK;
+ else
+ pmd_val(pmd) |= PMD_TYPE_SECT;
+
+ pmdp[0] = __pmd(pmd_val(pmd));
+ pmdp[1] = __pmd(pmd_val(pmd) + SECTION_SIZE);
+ }
+
+ flush_pmd_entry(pmdp);
+}
+
+#define pmd_modify(pmd, prot) \
+({ \
+ pmd_t pmdret = __pmd((pmd_val(pmd) \
+ & (PMD_MASK | PMD_DOMAIN_MASK)) \
+ | arm_hugepmdprotval); \
+ pgprot_t inprot = prot; \
+ pte_t newprot = __pte(pgprot_val(inprot)); \
+ \
+ if (pte_dirty(newprot)) \
+ pmdret = pmd_mkdirty(pmdret); \
+ else \
+ pmdret = pmd_mkclean(pmdret); \
+ \
+ if (pte_exec(newprot)) \
+ pmdret = pmd_mkexec(pmdret); \
+ else \
+ pmdret = pmd_mknexec(pmdret); \
+ \
+ if (pte_write(newprot)) \
+ pmdret = pmd_mkwrite(pmdret); \
+ else \
+ pmdret = pmd_wrprotect(pmdret); \
+ \
+ if (pte_young(newprot)) \
+ pmdret = pmd_mkyoung(pmdret); \
+ else \
+ pmdret = pmd_mkold(pmdret); \
+ \
+ if (pte_protnone(newprot)) \
+ pmdret = pmd_mkprotnone(pmdret); \
+ else \
+ pmdret = pmd_rmprotnone(pmdret); \
+ \
+ if (pte_val(newprot) & PMD_SECT_BUFFERABLE) \
+ pmdret |= PMD_SECT_BUFFERABLE; \
+ else \
+ pmdret &= ~PMD_SECT_BUFFERABLE; \
+ \
+ if (pte_val(newprot) & PMD_SECT_CACHEABLE) \
+ pmdret |= PMD_SECT_CACHEABLE; \
+ else \
+ pmdret &= ~PMD_SECT_CACHEABLE; \
+ \
+ if (pte_val(newprot) & L_PTE_MT_DEV_SHARED) \
+ pmdret |= PMD_SECT_TEX(1); \
+ else \
+ pmdret &= ~(PMD_SECT_TEX(1)); \
+ \
+ if (pte_val(newprot) & L_PTE_SHARED) \
+ pmdret |= PMD_SECT_S; \
+ else \
+ pmdret &= ~PMD_SECT_S; \
+ \
+ pmdret; \
+})
+
/*
* We don't have huge page support for short descriptors, for the moment
* define empty stubs for use by pin_page_for_write.
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 2b85d175e999..af53b40d1627 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -55,7 +55,7 @@
* Hugetlb definitions.
*/
#define HPAGE_SHIFT PMD_SHIFT
-#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_SIZE (_AC(1, ULL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index c02f24400369..e3a6ebcfe415 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -196,6 +196,10 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_young(pte) (pte_isset((pte), L_PTE_YOUNG))
#define pte_exec(pte) (pte_isclear((pte), L_PTE_XN))
+#ifdef CONFIG_NUMA_BALANCING
+#define pte_protnone(pte) (pte_val(pte) & L_PTE_NONE)
+#endif
+
#define pte_valid_user(pte) \
(pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte))
@@ -274,6 +278,16 @@ static inline pte_t pte_mknexec(pte_t pte)
return set_pte_bit(pte, __pgprot(L_PTE_XN));
}
+static inline pte_t pte_mkprotnone(pte_t pte)
+{
+ return set_pte_bit(pte, __pgprot(L_PTE_NONE));
+}
+
+static inline pte_t pte_rmprotnone(pte_t pte)
+{
+ return clear_pte_bit(pte, __pgprot(L_PTE_NONE));
+}
+
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index f8904227e7fd..dfc95659bb89 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -460,8 +460,12 @@ __enable_mmu:
#endif
#ifdef CONFIG_ARM_LPAE
mcrr p15, 0, r4, r5, c2 @ load TTBR0
+#else
+#ifdef CONFIG_SYS_SUPPORTS_HUGETLBFS
+ ldr r5, =0x55555555
#else
mov r5, #DACR_INIT
+#endif
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
#endif
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index efa402025031..9985bab5ee66 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -26,6 +26,10 @@
#ifdef CONFIG_MMU
+#if defined(CONFIG_SYS_SUPPORTS_HUGETLBFS) && !defined(CONFIG_ARM_LPAE)
+#include <linux/hugetlb.h>
+#endif
+
/*
* This is useful to dump out the page tables associated with
* 'addr' in mm 'mm'.
@@ -76,6 +80,15 @@ void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr)
break;
if (pmd_bad(*pmd)) {
+#if !defined(CONFIG_ARM_LPAE) && defined(CONFIG_HUGETLBFS)
+ if (pte_huge((pte_t)*pgd)) {
+ pte_t huge_pte = huge_ptep_get((pte_t *)pgd);
+
+ pr_alert("[%08lx] *ppgd=%08llx", addr,
+ (long long)pmd_val(huge_pte));
+ break;
+ }
+#endif
pr_cont("(bad)");
break;
}
@@ -462,19 +475,6 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
}
#endif /* CONFIG_MMU */
-/*
- * Some section permission faults need to be handled gracefully.
- * They can happen due to a __{get,put}_user during an oops.
- */
-#ifndef CONFIG_ARM_LPAE
-static int
-do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- do_bad_area(addr, fsr, regs);
- return 0;
-}
-#endif /* CONFIG_ARM_LPAE */
-
/*
* This abort handler always returns "fault".
*/
diff --git a/arch/arm/mm/fsr-2level.c b/arch/arm/mm/fsr-2level.c
index f2be95197265..f22e33ab0dc6 100644
--- a/arch/arm/mm/fsr-2level.c
+++ b/arch/arm/mm/fsr-2level.c
@@ -17,7 +17,7 @@ static struct fsr_info fsr_info[] = {
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
- { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
/*
@@ -57,7 +57,7 @@ static struct fsr_info ifsr_info[] = {
{ do_bad, SIGBUS, 0, "unknown 10" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
- { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
{ do_bad, SIGBUS, 0, "external abort on translation" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
{ do_bad, SIGBUS, 0, "unknown 16" },
diff --git a/arch/arm/mm/hugetlbpage.c b/arch/arm/mm/hugetlbpage.c
index dd7a0277c5c0..5ede7ef5e531 100644
--- a/arch/arm/mm/hugetlbpage.c
+++ b/arch/arm/mm/hugetlbpage.c
@@ -30,5 +30,5 @@ int pud_huge(pud_t pud)
int pmd_huge(pmd_t pmd)
{
- return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT);
+ return pmd_large(pmd);
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index ab69250a86bc..911ce69f04a0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -402,6 +402,20 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
}
+/*
+ * If the system supports huge pages and we are running with short descriptors,
+ * then compute the pmd and linux pte prot values for a huge page.
+ *
+ * These values are used by both the HugeTLB and THP code.
+ */
+#if defined(CONFIG_SYS_SUPPORTS_HUGETLBFS) && !defined(CONFIG_ARM_LPAE)
+pmdval_t arm_hugepmdprotval;
+EXPORT_SYMBOL(arm_hugepmdprotval);
+
+pteval_t arm_hugepteprotval;
+EXPORT_SYMBOL(arm_hugepteprotval);
+#endif
+
/*
* Adjust the PMD section entries according to the CPU in use.
*/
@@ -667,6 +681,17 @@ static void __init build_mem_type_table(void)
if (t->prot_sect)
t->prot_sect |= PMD_DOMAIN(t->domain);
}
+
+#if defined(CONFIG_SYS_SUPPORTS_HUGETLBFS) && !defined(CONFIG_ARM_LPAE)
+ /*
+ * we assume all huge pages are user pages and that hardware access
+ * flag updates are disabled (i.e. SCTLR.AFE == 0b).
+ */
+ arm_hugepteprotval = mem_types[MT_MEMORY_RWX].prot_pte | L_PTE_USER | L_PTE_VALID;
+
+ arm_hugepmdprotval = mem_types[MT_MEMORY_RWX].prot_sect | PMD_SECT_AP_READ
+ | PMD_SECT_nG;
+#endif
}
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
--
2.25.0
1
0
v2->v3:
remove the patch "Linux-5.10.1.patch"
v1->v2:
modifty the commit message:
linux-5.10.1 -> stable-5.10.1
*** BLURB HERE ***
Greg Kroah-Hartman (2):
Revert "md: change mddev 'chunk_sectors' from int to unsigned"
Revert "dm raid: fix discard limits for raid1 and raid10"
drivers/md/dm-raid.c | 12 +++++-------
drivers/md/md.h | 4 ++--
2 files changed, 7 insertions(+), 9 deletions(-)
--
2.25.0
1
2
[PATCH openEuler-1.0-LTS] defconfig: update the defconfigs to support NVDIMM
by Xie XiuQi 21 Dec '20
by Xie XiuQi 21 Dec '20
21 Dec '20
From: Hanjun Guo <guohanjun(a)huawei.com>
hulk inclusion
category: feature
feature: ACPI NVDIMM Firmware Interface Table (NFIT)
bugzilla: 46783
CVE: NA
Reference: https://gitee.com/open_euler/dashboard/issues?id=I26KWQ
Backport this patch from kernel-4.19 to openEuler 20.03 LTS SP1.
564e83bbdcae defconfig: update the defconfigs to support NVDIMM
---------------------------
openEuler wants NVDIMM support, update the defconfig.
Signed-off-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Xie XiuQi <xiexiuqi(a)huawei.com>
---
arch/arm64/configs/hulk_defconfig | 2 +-
arch/arm64/configs/openeuler_defconfig | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/configs/hulk_defconfig b/arch/arm64/configs/hulk_defconfig
index 20c7c527dc33..090ff6c93730 100644
--- a/arch/arm64/configs/hulk_defconfig
+++ b/arch/arm64/configs/hulk_defconfig
@@ -635,7 +635,7 @@ CONFIG_ACPI_HED=y
# CONFIG_ACPI_CUSTOM_METHOD is not set
# CONFIG_ACPI_BGRT is not set
CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y
-# CONFIG_ACPI_NFIT is not set
+CONFIG_ACPI_NFIT=m
CONFIG_HAVE_ACPI_APEI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index c68f4c9ee65c..5561751ad6eb 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -627,7 +627,7 @@ CONFIG_ACPI_HED=y
# CONFIG_ACPI_CUSTOM_METHOD is not set
# CONFIG_ACPI_BGRT is not set
CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y
-# CONFIG_ACPI_NFIT is not set
+CONFIG_ACPI_NFIT=m
CONFIG_HAVE_ACPI_APEI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
--
2.20.1
1
0
hi openEuler kernel team:
我是麒麟软件共性支撑部李志刚, 公司安排我将 TCM on SPI
的驱动移植到您的社区源码; 代码我已经核外编译验证过,
下一步请你们指导我将其放入你们社区(请告诉我最好放入哪个目录).
不好意思我没有社区开发经验, 请您告诉我如何开始好吧?
譬如是不需要我注册个账户, 最好有个简介性的文档.
TCM 是国民技术公司的类米国 TPM 芯片/产品, 用于安全和可信计算等.
麒麟软件 共性支撑部 李志刚
2020-12-18
2
2
From: Mingwang Li <limingwang(a)huawei.com>
euleros inclusion
category: feature
bugzilla: NA
CVE: NA
This series adds initial KVM RISC-V support. Currently, we are able to boot
Linux on RV64/RV32 Guest with multiple VCPUs.
This series can be found in riscv_kvm_v15 branch at:
https//github.com/avpatel/linux.git
Link: https://gitee.com/openeuler/kernel/issues/I26X9V
Alistair Francis (1):
Revert "riscv: Use latest system call ABI"
Anup Patel (19):
RISC-V: Add fragmented config for debug options
RISC-V: Enable CPU Hotplug in defconfigs
RISC-V: Add Microchip PolarFire kconfig option
RISC-V: Initial DTS for Microchip ICICLE board
RISC-V: Enable drivers for Microchip PolarFire ICICLE board
RISC-V: Add hypervisor extension related CSR defines
RISC-V: Add initial skeletal KVM support
RISC-V: KVM: Implement VCPU create, init and destroy functions
RISC-V: KVM: Implement VCPU interrupts and requests handling
RISC-V: KVM: Implement KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls
RISC-V: KVM: Implement VCPU world-switch
RISC-V: KVM: Handle MMIO exits for VCPU
RISC-V: KVM: Handle WFI exits for VCPU
RISC-V: KVM: Implement VMID allocator
RISC-V: KVM: Implement stage2 page table programming
RISC-V: KVM: Implement MMU notifiers
RISC-V: KVM: Document RISC-V specific parts of KVM API
RISC-V: KVM: Add MAINTAINERS entry
RISC-V: Enable KVM for RV64 and RV32
Atish Patra (4):
RISC-V: KVM: Add timer functionality
RISC-V: KVM: FP lazy save/restore
RISC-V: KVM: Implement ONE REG interface for FP registers
RISC-V: KVM: Add SBI v0.1 support
Mingwang Li (1):
RISCV: KVM: fix bug in migration
m34782 (1):
Microchip Polarfire SoC Clock Driver
Documentation/virt/kvm/api.rst | 193 +++-
MAINTAINERS | 11 +
arch/riscv/Kconfig | 2 +
arch/riscv/Kconfig.socs | 7 +
arch/riscv/Makefile | 2 +
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/microchip/Makefile | 2 +
.../boot/dts/microchip/icicle-kit-es.dts | 307 +++++
arch/riscv/configs/defconfig | 30 +-
arch/riscv/configs/extra_debug.config | 21 +
arch/riscv/configs/rv32_defconfig | 26 +-
arch/riscv/include/asm/csr.h | 89 ++
arch/riscv/include/asm/kvm_host.h | 278 +++++
arch/riscv/include/asm/kvm_types.h | 7 +
arch/riscv/include/asm/kvm_vcpu_timer.h | 44 +
arch/riscv/include/asm/pgtable-bits.h | 1 +
arch/riscv/include/uapi/asm/kvm.h | 128 +++
arch/riscv/include/uapi/asm/unistd.h | 5 +-
arch/riscv/kernel/asm-offsets.c | 156 +++
arch/riscv/kvm/Kconfig | 36 +
arch/riscv/kvm/Makefile | 15 +
arch/riscv/kvm/main.c | 118 ++
arch/riscv/kvm/mmu.c | 860 ++++++++++++++
arch/riscv/kvm/tlb.S | 74 ++
arch/riscv/kvm/vcpu.c | 1012 +++++++++++++++++
arch/riscv/kvm/vcpu_exit.c | 701 ++++++++++++
arch/riscv/kvm/vcpu_sbi.c | 173 +++
arch/riscv/kvm/vcpu_switch.S | 400 +++++++
arch/riscv/kvm/vcpu_timer.c | 225 ++++
arch/riscv/kvm/vm.c | 81 ++
arch/riscv/kvm/vmid.c | 120 ++
drivers/clk/Kconfig | 5 +
drivers/clk/Makefile | 1 +
drivers/clk/microchip/Makefile | 2 +
drivers/clk/microchip/clk-pfsoc.c | 508 +++++++++
drivers/clocksource/timer-riscv.c | 8 +
include/clocksource/timer-riscv.h | 16 +
include/uapi/linux/kvm.h | 8 +
38 files changed, 5619 insertions(+), 54 deletions(-)
create mode 100644 arch/riscv/boot/dts/microchip/Makefile
create mode 100644 arch/riscv/boot/dts/microchip/icicle-kit-es.dts
create mode 100644 arch/riscv/configs/extra_debug.config
create mode 100644 arch/riscv/include/asm/kvm_host.h
create mode 100644 arch/riscv/include/asm/kvm_types.h
create mode 100644 arch/riscv/include/asm/kvm_vcpu_timer.h
create mode 100644 arch/riscv/include/uapi/asm/kvm.h
create mode 100644 arch/riscv/kvm/Kconfig
create mode 100644 arch/riscv/kvm/Makefile
create mode 100644 arch/riscv/kvm/main.c
create mode 100644 arch/riscv/kvm/mmu.c
create mode 100644 arch/riscv/kvm/tlb.S
create mode 100644 arch/riscv/kvm/vcpu.c
create mode 100644 arch/riscv/kvm/vcpu_exit.c
create mode 100644 arch/riscv/kvm/vcpu_sbi.c
create mode 100644 arch/riscv/kvm/vcpu_switch.S
create mode 100644 arch/riscv/kvm/vcpu_timer.c
create mode 100644 arch/riscv/kvm/vm.c
create mode 100644 arch/riscv/kvm/vmid.c
create mode 100644 drivers/clk/microchip/clk-pfsoc.c
create mode 100644 include/clocksource/timer-riscv.h
--
2.19.1
2
27
17 Dec '20
From: Chiqijun <chiqijun(a)huawei.com>
driver inclusion
category: bugfix
bugzilla: 4472
-----------------------------------------------------------------------
In the x86 system, the hinic device turns off LRO by default, and the
LRO state will not be set when the driver is loaded. If the LRO of the
chip is turned on before the driver is loaded, it will cause the chip
to still turn on LRO after reloading the driver, but the LRO that the
user sees is turned off. Therefore, the driver is forced to set the
default features of the device when probe.
Signed-off-by: Chiqijun <chiqijun(a)huawei.com>
Reviewed-by: Wangxiaoyun <cloud.wangxiaoyun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/net/ethernet/huawei/hinic/hinic_main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index cf7b6ceef060..26cd2929f60a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -1491,7 +1491,7 @@ static int set_feature_lro(struct hinic_nic_dev *nic_dev,
static int set_features(struct hinic_nic_dev *nic_dev,
netdev_features_t pre_features,
- netdev_features_t features, bool force_change)
+ netdev_features_t features)
{
netdev_features_t failed_features = 0;
u32 err;
@@ -1518,7 +1518,7 @@ static int hinic_set_features(struct net_device *netdev,
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
return set_features(nic_dev, nic_dev->netdev->features,
- features, false);
+ features);
}
static netdev_features_t hinic_fix_features(struct net_device *netdev,
@@ -1563,7 +1563,8 @@ static int hinic_set_default_hw_feature(struct hinic_nic_dev *nic_dev)
}
/* enable all hw features in netdev->features */
- return set_features(nic_dev, 0, nic_dev->netdev->features, true);
+ return set_features(nic_dev, ~nic_dev->netdev->features,
+ nic_dev->netdev->features);
}
static int hinic_setup_tc_mqprio(struct net_device *dev,
--
2.25.1
1
3
17 Dec '20
From: Jan Kara <jack(a)suse.cz>
hulk inclusion
category: bugfix
bugzilla: 46758
CVE: NA
---------------------------
Protect all superblock modifications (including checksum computation)
with a superblock buffer lock. That way we are sure computed checksum
matches current superblock contents (a mismatch could cause checksum
failures in nojournal mode or if an unjournalled superblock update races
with a journalled one). Also we avoid modifying superblock contents
while it is being written out (which can cause DIF/DIX failures if we
are running in nojournal mode).
Signed-off-by: Jan Kara <jack(a)suse.cz>
[backport the 10th patch:
https://www.spinics.net/lists/linux-ext4/msg75423.html
drop the other lock_buffer besides operation for orphan]
Signed-off-by: yangerkun <yangerkun(a)huawei.com>
Reviewed-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/ext4/ext4_jbd2.c | 1 -
fs/ext4/file.c | 1 +
fs/ext4/inode.c | 1 +
fs/ext4/namei.c | 6 ++++++
fs/ext4/resize.c | 4 ++++
fs/ext4/xattr.c | 1 +
6 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index a589b7f79558..f9ac7dfd93bf 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -361,7 +361,6 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
int err = 0;
- ext4_superblock_csum_set(sb);
if (ext4_handle_valid(handle)) {
err = jbd2_journal_dirty_metadata(handle, bh);
if (err)
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 52d155b4e733..1703871fa2d0 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -434,6 +434,7 @@ static int ext4_sample_last_mounted(struct super_block *sb,
goto out_journal;
strlcpy(sbi->s_es->s_last_mounted, cp,
sizeof(sbi->s_es->s_last_mounted));
+ ext4_superblock_csum_set(sb);
ext4_handle_dirty_super(handle, sb);
out_journal:
ext4_journal_stop(handle);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 8d7e2cd9ae37..6ee89cd7a408 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5398,6 +5398,7 @@ static int ext4_do_update_inode(handle_t *handle,
if (err)
goto out_brelse;
ext4_set_feature_large_file(sb);
+ ext4_superblock_csum_set(sb);
ext4_handle_sync(handle);
err = ext4_handle_dirty_super(handle, sb);
}
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index ffc3695eb153..762eb6913240 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2889,7 +2889,10 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
(le32_to_cpu(sbi->s_es->s_inodes_count))) {
/* Insert this inode at the head of the on-disk orphan list */
NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan);
+ lock_buffer(sbi->s_sbh);
sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
+ ext4_superblock_csum_set(sb);
+ unlock_buffer(sbi->s_sbh);
dirty = true;
}
list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan);
@@ -2972,7 +2975,10 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
mutex_unlock(&sbi->s_orphan_lock);
goto out_brelse;
}
+ lock_buffer(sbi->s_sbh);
sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
+ ext4_superblock_csum_set(inode->i_sb);
+ unlock_buffer(sbi->s_sbh);
mutex_unlock(&sbi->s_orphan_lock);
err = ext4_handle_dirty_super(handle, inode->i_sb);
} else {
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 6a0c5c880354..c2e007d836e4 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -901,6 +901,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
ext4_kvfree_array_rcu(o_group_desc);
le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
+ ext4_superblock_csum_set(sb);
err = ext4_handle_dirty_super(handle, sb);
if (err)
ext4_std_error(sb, err);
@@ -1423,6 +1424,7 @@ static void ext4_update_super(struct super_block *sb,
* active. */
ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +
reserved_blocks);
+ ext4_superblock_csum_set(sb);
/* Update the free space counts */
percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -1721,6 +1723,7 @@ static int ext4_group_extend_no_check(struct super_block *sb,
ext4_blocks_count_set(es, o_blocks_count + add);
ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + add);
+ ext4_superblock_csum_set(sb);
ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add);
/* We add the blocks to the bitmap and set the group need init bit */
@@ -1882,6 +1885,7 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
ext4_set_feature_meta_bg(sb);
sbi->s_es->s_first_meta_bg =
cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count));
+ ext4_superblock_csum_set(sb);
err = ext4_handle_dirty_super(handle, sb);
if (err) {
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 24cf730ba6b0..ae029dccebc1 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -791,6 +791,7 @@ static void ext4_xattr_update_super_block(handle_t *handle,
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
ext4_set_feature_xattr(sb);
+ ext4_superblock_csum_set(sb);
ext4_handle_dirty_super(handle, sb);
}
}
--
2.25.1
1
1
[PATCH 01/15] arm64: KVM: Remove some extra semicolon in kvm_target_cpu
by Yang Yingliang 17 Dec '20
by Yang Yingliang 17 Dec '20
17 Dec '20
From: zhong jiang <zhongjiang(a)huawei.com>
mainline inclusion
from mainline-4.20
commit f0725345e3e127032376e4fcb6b0fc893237fcef
category: bugfix
bugzilla: NA
CVE: NA
-------------------------------------------------
There are some extra semicolon in kvm_target_cpu, remove it.
Signed-off-by: zhong jiang <zhongjiang(a)huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier(a)arm.com>
Signed-off-by: Xiangyou Xie <xiexiangyou(a)huawei.com>
Reviewed-by: Ying Fang <fangying1(a)huawei.com>
Reviewed-by: Zenghui Yu <yuzenghui(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/arm64/kvm/guest.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index ff9908c5d496..ff00e1c8023a 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -432,15 +432,15 @@ int __attribute_const__ kvm_target_cpu(void)
return KVM_ARM_TARGET_CORTEX_A53;
case ARM_CPU_PART_CORTEX_A57:
return KVM_ARM_TARGET_CORTEX_A57;
- };
+ }
break;
case ARM_CPU_IMP_APM:
switch (part_number) {
case APM_CPU_PART_POTENZA:
return KVM_ARM_TARGET_XGENE_POTENZA;
- };
+ }
break;
- };
+ }
/* Return a default generic target */
return KVM_ARM_TARGET_GENERIC_V8;
--
2.25.1
1
14
[PATCH] mm: thp: make the THP mapcount atomic against __split_huge_pmd_locked()
by Yang Yingliang 17 Dec '20
by Yang Yingliang 17 Dec '20
17 Dec '20
From: Andrea Arcangeli <aarcange(a)redhat.com>
stable inclusion
from linux-4.19.129
commit 453d8a481b127edfa7fb76af1bc7586b7a63bdd2
CVE: CVE-2020-29368
--------------------------------
commit c444eb564fb16645c172d550359cb3d75fe8a040 upstream.
Write protect anon page faults require an accurate mapcount to decide
if to break the COW or not. This is implemented in the THP path with
reuse_swap_page() ->
page_trans_huge_map_swapcount()/page_trans_huge_mapcount().
If the COW triggers while the other processes sharing the page are
under a huge pmd split, to do an accurate reading, we must ensure the
mapcount isn't computed while it's being transferred from the head
page to the tail pages.
reuse_swap_cache() already runs serialized by the page lock, so it's
enough to add the page lock around __split_huge_pmd_locked too, in
order to add the missing serialization.
Note: the commit in "Fixes" is just to facilitate the backporting,
because the code before such commit didn't try to do an accurate THP
mapcount calculation and it instead used the page_count() to decide if
to COW or not. Both the page_count and the pin_count are THP-wide
refcounts, so they're inaccurate if used in
reuse_swap_page(). Reverting such commit (besides the unrelated fix to
the local anon_vma assignment) would have also opened the window for
memory corruption side effects to certain workloads as documented in
such commit header.
Signed-off-by: Andrea Arcangeli <aarcange(a)redhat.com>
Suggested-by: Jann Horn <jannh(a)google.com>
Reported-by: Jann Horn <jannh(a)google.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov(a)linux.intel.com>
Fixes: 6d0a07edd17c ("mm: thp: calculate the mapcount correctly for THP pages during WP faults")
Cc: stable(a)vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/huge_memory.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index b60cbf77e902..816a7fd3c6ff 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2286,6 +2286,8 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
spinlock_t *ptl;
struct mm_struct *mm = vma->vm_mm;
unsigned long haddr = address & HPAGE_PMD_MASK;
+ bool was_locked = false;
+ pmd_t _pmd;
mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PMD_SIZE);
ptl = pmd_lock(mm, pmd);
@@ -2295,11 +2297,32 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
* pmd against. Otherwise we can end up replacing wrong page.
*/
VM_BUG_ON(freeze && !page);
- if (page && page != pmd_page(*pmd))
- goto out;
+ if (page) {
+ VM_WARN_ON_ONCE(!PageLocked(page));
+ was_locked = true;
+ if (page != pmd_page(*pmd))
+ goto out;
+ }
+repeat:
if (pmd_trans_huge(*pmd)) {
- page = pmd_page(*pmd);
+ if (!page) {
+ page = pmd_page(*pmd);
+ if (unlikely(!trylock_page(page))) {
+ get_page(page);
+ _pmd = *pmd;
+ spin_unlock(ptl);
+ lock_page(page);
+ spin_lock(ptl);
+ if (unlikely(!pmd_same(*pmd, _pmd))) {
+ unlock_page(page);
+ put_page(page);
+ page = NULL;
+ goto repeat;
+ }
+ put_page(page);
+ }
+ }
if (PageMlocked(page))
clear_page_mlock(page);
} else if (!(pmd_devmap(*pmd) || is_pmd_migration_entry(*pmd)))
@@ -2307,6 +2330,8 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
__split_huge_pmd_locked(vma, pmd, haddr, freeze);
out:
spin_unlock(ptl);
+ if (!was_locked && page)
+ unlock_page(page);
/*
* No need to double call mmu_notifier->invalidate_range() callback.
* They are 3 cases to consider inside __split_huge_pmd_locked():
--
2.25.1
1
0
17 Dec '20
From: Jann Horn <jannh(a)google.com>
stable inclusion
from linux-4.19.142
commit 9660983738399465fd0e3b1977a61bbd29b2e5be
CVE: CVE-2020-29371
--------------------------------
commit bcf85fcedfdd17911982a3e3564fcfec7b01eebd upstream.
romfs has a superblock field that limits the size of the filesystem; data
beyond that limit is never accessed.
romfs_dev_read() fetches a caller-supplied number of bytes from the
backing device. It returns 0 on success or an error code on failure;
therefore, its API can't represent short reads, it's all-or-nothing.
However, when romfs_dev_read() detects that the requested operation would
cross the filesystem size limit, it currently silently truncates the
requested number of bytes. This e.g. means that when the content of a
file with size 0x1000 starts one byte before the filesystem size limit,
->readpage() will only fill a single byte of the supplied page while
leaving the rest uninitialized, leaking that uninitialized memory to
userspace.
Fix it by returning an error code instead of truncating the read when the
requested read operation would go beyond the end of the filesystem.
Fixes: da4458bda237 ("NOMMU: Make it possible for RomFS to use MTD devices directly")
Signed-off-by: Jann Horn <jannh(a)google.com>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
Reviewed-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Cc: David Howells <dhowells(a)redhat.com>
Cc: <stable(a)vger.kernel.org>
Link: http://lkml.kernel.org/r/20200818013202.2246365-1-jannh@google.com
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/romfs/storage.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/fs/romfs/storage.c b/fs/romfs/storage.c
index f86f51f99ace..1dcadd22b440 100644
--- a/fs/romfs/storage.c
+++ b/fs/romfs/storage.c
@@ -221,10 +221,8 @@ int romfs_dev_read(struct super_block *sb, unsigned long pos,
size_t limit;
limit = romfs_maxsize(sb);
- if (pos >= limit)
+ if (pos >= limit || buflen > limit - pos)
return -EIO;
- if (buflen > limit - pos)
- buflen = limit - pos;
#ifdef CONFIG_ROMFS_ON_MTD
if (sb->s_mtd)
--
2.25.1
1
0
v1->v2
modifty the commit message:
linux-5.10.1 -> stable-5.10.1
*** BLURB HERE ***
Greg Kroah-Hartman (3):
Revert "md: change mddev 'chunk_sectors' from int to unsigned"
Revert "dm raid: fix discard limits for raid1 and raid10"
Linux 5.10.1
Makefile | 2 +-
drivers/md/dm-raid.c | 12 +++++-------
drivers/md/md.h | 4 ++--
3 files changed, 8 insertions(+), 10 deletions(-)
--
2.25.0
2
6
*** BLURB HERE ***
Greg Kroah-Hartman (3):
Revert "md: change mddev 'chunk_sectors' from int to unsigned"
Revert "dm raid: fix discard limits for raid1 and raid10"
Linux 5.10.1
Makefile | 2 +-
drivers/md/dm-raid.c | 12 +++++-------
drivers/md/md.h | 4 ++--
3 files changed, 8 insertions(+), 10 deletions(-)
--
2.25.0
2
6
嗨,各位 openEuler 社区的开发者:
很高兴能够向你们汇报 openEuler Summit 的会议进度。对于各位来说,本周最重要的事情是 TC、Maintainer和SIG
组开放工作会议的议程已经上线了。
*为什么你一定要参与 TC、Maintainer、SIG组开放工作会议?*
1. 你可以清楚的了解 openEuler 社区的运作模式
2. 你可以和 TC、Maintainer、SIG 的成员共同探讨openEuler 社区的下一个版本的计划和技术路线
3. 可以跟社区里的技术大佬进行面对面交流。
4. 更好的规划自己在社区中的成长路线
*会议时间和房间号:*
TC 开放工作会议
Maintainer 开放工作会议
SIG 组开放工作会议
时间
12/24 13:00-14:30
12/24 15:00-17:00
12/25 13:00-15:30
房间号
悦府6和悦府7
悦府6和悦府7
大宴会厅B
*TC **开放工作会议议程:*
1. 讨论 openEuler 支持 App Stream 机制
2. 申请成立智能运维 SIG
3. 讨论从 Gitee issue 整体切换到bugzilla
4. 讨论2021年 TC 合作的开展方式
5. ……
*Maintainer **开放工作会议议程*
1. 开场 & 颁发 Maintainer 纪念徽章
2. openEuler 社区运作分析
3. 我在 openEuler 社区担任 Maintainer 的那些事儿
4. 自由问答
5. 总结
*参与本次 SIG 组开放工作会议的 SIG 组:*
1. sig-DDE
2. sig-UKUI
3. sig-Ha
4. sig-arrch32
5. A-Tune
6. iSulad & Container
7. sig-ai-bitdata
8. sig-security-facility
9. sig-confidential-computing
10. Compiler
11. Doc
12. Infrastructure
13. security-committee
14. sig-Compatibility-Infra
15. sig-QA
16. sig-release-management
17. Kernel
18. Virt
*openEuler Summit **专属伴手礼:*
[image: image.png]
*openEuler **卫衣*
[image: image.png]
*openEuler Maintainer **纪念徽章*
*欢迎通过openEuler 社区开发者专属的报名渠道报名:*
https://etherpad.openeuler.org/p/openEuler-Summit-2020
openEuler Summit 官网:
https://openeuler.org/zh/interaction/summit-list/
1
0
[PATCH 1/2] arm64: arch_timer: only do cntvct workaround on VDSO path on D05
by Yang Yingliang 16 Dec '20
by Yang Yingliang 16 Dec '20
16 Dec '20
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
--------------------------------
On other board do do cntvct workaround on VDSO path may cause unexpected
error, so we do this only on D05.
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/clocksource/arm_arch_timer.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 443079810300..50030326d27b 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -551,9 +551,14 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa
* change both the default value and the vdso itself.
*/
if (wa->read_cntvct_el0) {
- clocksource_counter.archdata.vdso_direct = true;
- vdso_default = true;
- vdso_fix = true;
+ if (wa->read_cntvct_el0 == hisi_161010101_read_cntvct_el0) {
+ clocksource_counter.archdata.vdso_direct = true;
+ vdso_default = true;
+ vdso_fix = true;
+ } else {
+ clocksource_counter.archdata.vdso_direct = false;
+ vdso_default = false;
+ }
}
}
--
2.25.1
1
1
From: Wu Bo <wubo40(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
https://gitee.com/src-openeuler/kernel/issues/I28N9J
---------------------------
For some reason, during reboot the system, iscsi.service failed to
logout all sessions. kernel will hang forever on its
sd_sync_cache() logic, after issuing the SYNCHRONIZE_CACHE cmd to all
still existent paths.
[ 1044.098991] reboot: Mddev shutdown finished.
[ 1044.099311] reboot: Usermodehelper disable finished.
[ 1050.611244] connection2:0: ping timeout of 5 secs expired, recv timeout 5,
last rx 4295152378, last ping 4295153633, now 4295154944
[ 1348.599676] Call trace:
[ 1348.599887] __switch_to+0xe8/0x150
[ 1348.600113] __schedule+0x33c/0xa08
[ 1348.600372] schedule+0x2c/0x88
[ 1348.600567] schedule_timeout+0x184/0x3a8
[ 1348.600820] io_schedule_timeout+0x28/0x48
[ 1348.601089] wait_for_common_io.constprop.2+0x168/0x258
[ 1348.601425] wait_for_completion_io_timeout+0x28/0x38
[ 1348.601762] blk_execute_rq+0x98/0xd8
[ 1348.602006] __scsi_execute+0xe0/0x1e8
[ 1348.602262] sd_sync_cache+0xd0/0x220 [sd_mod]
[ 1348.602551] sd_shutdown+0x6c/0xf8 [sd_mod]
[ 1348.602826] device_shutdown+0x13c/0x250
[ 1348.603078] kernel_restart_prepare+0x5c/0x68
[ 1348.603400] kernel_restart+0x20/0x98
[ 1348.603683] __se_sys_reboot+0x214/0x260
[ 1348.603987] __arm64_sys_reboot+0x24/0x30
[ 1348.604300] el0_svc_common+0x80/0x1b8
[ 1348.604590] el0_svc_handler+0x78/0xe0
[ 1348.604877] el0_svc+0x10/0x260
d754941225 (scsi: libiscsi: Allow sd_shutdown on bad transport) Once
solved this problem. The iscsi_eh_cmd_timed_out() function add system_state
judgment, and will return BLK_EH_DONE and mark the result as
DID_NO_CONNECT when system_state is not SYSTEM_RUNNING,
To tell upper layers that the command was handled during
the transport layer error handler helper.
The scsi Mid Layer timeout handler function(scsi_times_out) will be
abort the cmd if the scsi LLD timeout handler return BLK_EH_DONE.
if abort cmd failed, will enter scsi EH logic.
Scsi EH will do reset target logic, if reset target failed, Will
call iscsi_eh_session_reset() function to drop the session.
The iscsi_eh_session_reset function will wait for a relogin,
session termination from userspace, or a recovery/replacement timeout.
But at this time, the app iscsid has exited, and the session was marked as
ISCSI_STATE_FAILED, So the SCSI EH process will never be
scheduled back again.
PID: 9123 TASK: ffff80020c1b4d80 CPU: 3 COMMAND: "scsi_eh_2"
#0 [ffff00008632bb70] __switch_to at ffff000080088738
#1 [ffff00008632bb90] __schedule at ffff000080a00480
#2 [ffff00008632bc20] schedule at ffff000080a00b58
#3 [ffff00008632bc30] iscsi_eh_session_reset at ffff000000d1ab9c [libiscsi]
#4 [ffff00008632bcb0] iscsi_eh_recover_target at ffff000000d1d1fc [libiscsi]
#5 [ffff00008632bd00] scsi_try_target_reset at ffff0000806f0bac
#6 [ffff00008632bd30] scsi_eh_ready_devs at ffff0000806f2724
#7 [ffff00008632bde0] scsi_error_handler at ffff0000806f41d4
#8 [ffff00008632be70] kthread at ffff000080119ae0
Reported-by: Tianxiong Lu <lutianxiong(a)huawei.com>
Signed-off-by: Wu Bo <wubo40(a)huawei.com>
Signed-off-by: Yu Kuai <yukuai3(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/libiscsi.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index ec356e035c5f..35d603db33bb 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2441,7 +2441,17 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc)
mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->frwd_lock);
- if (session->state == ISCSI_STATE_TERMINATE) {
+
+ /*
+ * During shutdown, if session is prematurely disconnected, recovery
+ * won't happen and there will be hung cmds. To solve this case, all
+ * cmds would be enter scsi EH, but the EH path will wait for
+ * wait_event_interruptible() to complete until the state of the
+ * session is ISCSI_STATE_TERMINATE, ISCSI_STATE_LOGGED_IN or
+ * ISCSI_STATE_RECOVERY_FAILED.
+ */
+ if (session->state == ISCSI_STATE_TERMINATE ||
+ unlikely(system_state != SYSTEM_RUNNING)) {
failed:
ISCSI_DBG_EH(session,
"failing session reset: Could not log back into "
--
2.25.1
1
0
[PATCH] scsi: iscsi: Perform connection failure entirely in kernel space
by Yang Yingliang 15 Dec '20
by Yang Yingliang 15 Dec '20
15 Dec '20
From: Bharath Ravi <rbharath(a)google.com>
mainline inclusion
from mainline-v5.7-rc1
commit 0ab710458da113a71c461c4df27e7f1353d9f864
category: bugfix
bugzilla: NA
CVE: NA
https://gitee.com/src-openeuler/kernel/issues/I28N9J
--------------------------------
Connection failure processing depends on a daemon being present to (at
least) stop the connection and start recovery. This is a problem on a
multipath scenario, where if the daemon failed for whatever reason, the
SCSI path is never marked as down, multipath won't perform the failover and
IO to the device will be forever waiting for that connection to come back.
This patch performs the connection failure entirely inside the kernel.
This way, the failover can happen and pending IO can continue even if the
daemon is dead. Once the daemon comes alive again, it can execute recovery
procedures if applicable.
Cc: Mike Christie <mchristi(a)redhat.com>
Cc: Lee Duncan <LDuncan(a)suse.com>
Cc: Bart Van Assche <bvanassche(a)acm.org>
Link: https://lore.kernel.org/r/20200125061925.191601-1-krisman@collabora.com
Co-developed-by: Dave Clausen <dclausen(a)google.com>
Co-developed-by: Nick Black <nlb(a)google.com>
Co-developed-by: Vaibhav Nagarnaik <vnagarnaik(a)google.com>
Co-developed-by: Anatol Pomazau <anatol(a)google.com>
Co-developed-by: Tahsin Erdogan <tahsin(a)google.com>
Co-developed-by: Frank Mayhar <fmayhar(a)google.com>
Co-developed-by: Junho Ryu <jayr(a)google.com>
Co-developed-by: Khazhismel Kumykov <khazhy(a)google.com>
Reviewed-by: Reviewed-by: Khazhismel Kumykov <khazhy(a)google.com>
Co-developed-by: Gabriel Krisman Bertazi <krisman(a)collabora.com>
Reviewed-by: Lee Duncan <lduncan(a)suse.com>
Signed-off-by: Bharath Ravi <rbharath(a)google.com>
Signed-off-by: Dave Clausen <dclausen(a)google.com>
Signed-off-by: Nick Black <nlb(a)google.com>
Signed-off-by: Vaibhav Nagarnaik <vnagarnaik(a)google.com>
Signed-off-by: Anatol Pomazau <anatol(a)google.com>
Signed-off-by: Tahsin Erdogan <tahsin(a)google.com>
Signed-off-by: Frank Mayhar <fmayhar(a)google.com>
Signed-off-by: Junho Ryu <jayr(a)google.com>
Signed-off-by: Khazhismel Kumykov <khazhy(a)google.com>
Signed-off-by: Gabriel Krisman Bertazi <krisman(a)collabora.com>
Signed-off-by: Martin K. Petersen <martin.petersen(a)oracle.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/scsi_transport_iscsi.c | 68 +++++++++++++++++++++++++++++
include/scsi/scsi_transport_iscsi.h | 1 +
2 files changed, 69 insertions(+)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 698347301198..e1ac96b8940b 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -81,6 +81,12 @@ struct iscsi_internal {
struct transport_container session_cont;
};
+/* Worker to perform connection failure on unresponsive connections
+ * completely in kernel space.
+ */
+static void stop_conn_work_fn(struct work_struct *work);
+static DECLARE_WORK(stop_conn_work, stop_conn_work_fn);
+
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
static struct workqueue_struct *iscsi_eh_timer_workq;
@@ -1609,6 +1615,7 @@ static DEFINE_MUTEX(rx_queue_mutex);
static LIST_HEAD(sesslist);
static DEFINE_SPINLOCK(sesslock);
static LIST_HEAD(connlist);
+static LIST_HEAD(connlist_err);
static DEFINE_SPINLOCK(connlock);
static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
@@ -2247,6 +2254,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
mutex_init(&conn->ep_mutex);
INIT_LIST_HEAD(&conn->conn_list);
+ INIT_LIST_HEAD(&conn->conn_list_err);
conn->transport = transport;
conn->cid = cid;
@@ -2293,6 +2301,7 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
spin_lock_irqsave(&connlock, flags);
list_del(&conn->conn_list);
+ list_del(&conn->conn_list_err);
spin_unlock_irqrestore(&connlock, flags);
transport_unregister_device(&conn->dev);
@@ -2407,6 +2416,51 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
}
EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
+static void stop_conn_work_fn(struct work_struct *work)
+{
+ struct iscsi_cls_conn *conn, *tmp;
+ unsigned long flags;
+ LIST_HEAD(recovery_list);
+
+ spin_lock_irqsave(&connlock, flags);
+ if (list_empty(&connlist_err)) {
+ spin_unlock_irqrestore(&connlock, flags);
+ return;
+ }
+ list_splice_init(&connlist_err, &recovery_list);
+ spin_unlock_irqrestore(&connlock, flags);
+
+ list_for_each_entry_safe(conn, tmp, &recovery_list, conn_list_err) {
+ uint32_t sid = iscsi_conn_get_sid(conn);
+ struct iscsi_cls_session *session;
+
+ mutex_lock(&rx_queue_mutex);
+
+ session = iscsi_session_lookup(sid);
+ if (session) {
+ if (system_state != SYSTEM_RUNNING) {
+ session->recovery_tmo = 0;
+ conn->transport->stop_conn(conn,
+ STOP_CONN_TERM);
+ } else {
+ conn->transport->stop_conn(conn,
+ STOP_CONN_RECOVER);
+ }
+ }
+
+ list_del_init(&conn->conn_list_err);
+
+ mutex_unlock(&rx_queue_mutex);
+
+ /* we don't want to hold rx_queue_mutex for too long,
+ * for instance if many conns failed at the same time,
+ * since this stall other iscsi maintenance operations.
+ * Give other users a chance to proceed.
+ */
+ cond_resched();
+ }
+}
+
void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
{
struct nlmsghdr *nlh;
@@ -2414,6 +2468,12 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
struct iscsi_uevent *ev;
struct iscsi_internal *priv;
int len = nlmsg_total_size(sizeof(*ev));
+ unsigned long flags;
+
+ spin_lock_irqsave(&connlock, flags);
+ list_add(&conn->conn_list_err, &connlist_err);
+ spin_unlock_irqrestore(&connlock, flags);
+ queue_work(system_unbound_wq, &stop_conn_work);
priv = iscsi_if_transport_lookup(conn->transport);
if (!priv)
@@ -2743,11 +2803,19 @@ static int
iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
{
struct iscsi_cls_conn *conn;
+ unsigned long flags;
conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
if (!conn)
return -EINVAL;
+ spin_lock_irqsave(&connlock, flags);
+ if (!list_empty(&conn->conn_list_err)) {
+ spin_unlock_irqrestore(&connlock, flags);
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&connlock, flags);
+
ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
if (transport->destroy_conn)
transport->destroy_conn(conn);
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index b266d2a3bcb1..7de0bf6a9b60 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -203,6 +203,7 @@ extern void iscsi_ping_comp_event(uint32_t host_no,
struct iscsi_cls_conn {
struct list_head conn_list; /* item in connlist */
+ struct list_head conn_list_err; /* item in connlist_err */
void *dd_data; /* LLD private data */
struct iscsi_transport *transport;
uint32_t cid; /* connection id */
--
2.25.1
1
0
Bjørn Mork (1):
USB: serial: option: fix Quectel BG96 matching
Bob Peterson (1):
gfs2: check for empty rgrp tree in gfs2_ri_update
Christian Eggers (3):
i2c: imx: Don't generate STOP condition if arbitration has been lost
i2c: imx: Fix reset of I2SR_IAL flag
i2c: imx: Check for I2SR_IAL after every byte
Florian Westphal (1):
netfilter: nf_tables: avoid false-postive lockdep splat
Giacinto Cifelli (1):
USB: serial: option: add support for Thales Cinterion EXS82
Greg Kroah-Hartman (1):
Linux 4.19.163
Hans de Goede (2):
pinctrl: baytrail: Replace WARN with dev_info_once when setting
direct-irq pin to output
pinctrl: baytrail: Fix pin being driven low for a while on
gpiod_get(..., GPIOD_OUT_HIGH)
Jakub Kicinski (1):
Revert "geneve: pull IP header before ECN decapsulation"
Jan-Niklas Burfeind (1):
USB: serial: ch341: add new Product ID for CH341A
Jian-Hong Pan (1):
ALSA: hda/realtek: Enable headset of ASUS UX482EG & B9400CEA with
ALC294
Johan Hovold (2):
USB: serial: kl5kusb105: fix memleak on open
USB: serial: ch341: sort device-id entries
Kailang Yang (1):
ALSA: hda/realtek - Add new codec supported for ALC897
Lukas Wunner (3):
spi: Introduce device-managed SPI controller allocation
spi: bcm-qspi: Fix use-after-free on unbind
spi: bcm2835: Fix use-after-free on unbind
Luo Meng (1):
Input: i8042 - fix error return code in i8042_setup_aux()
Masami Hiramatsu (2):
x86/uprobes: Do not use prefixes.nbytes when looping over
prefixes.bytes
x86/insn-eval: Use new for_each_insn_prefix() macro to loop over
prefixes bytes
Mike Snitzer (2):
dm: remove invalid sparse __acquires and __releases annotations
dm writecache: remove BUG() and fail gracefully instead
Mikulas Patocka (1):
dm writecache: fix the maximum number of arguments
Naveen N. Rao (1):
ftrace: Fix updating FTRACE_FL_TRAMP
Paulo Alcantara (1):
cifs: fix potential use-after-free in cifs_echo_request()
Peter Ujfalusi (1):
spi: bcm2835: Release the DMA channel if probe fails after dma_init
Qian Cai (1):
mm/swapfile: do not sleep with a spin lock held
Steven Rostedt (VMware) (1):
tracing: Fix userstacktrace option for instances
Suganath Prabu S (1):
scsi: mpt3sas: Fix ioctl timeout
Suravee Suthikulpanit (1):
iommu/amd: Set DTE[IntTabLen] to represent 512 IRTEs
Takashi Iwai (2):
ALSA: hda/realtek: Add mute LED quirk to yet another HP x360 model
ALSA: hda/generic: Add option to enforce preferred_dacs pairs
Vamsi Krishna Samavedam (1):
usb: gadget: f_fs: Use local copy of descriptors for userspace copy
Vincent Palatin (1):
USB: serial: option: add Fibocom NL668 variants
Yang Shi (1):
mm: list_lru: set shrinker map bit when child nr_items is not zero
Zhihao Cheng (1):
i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc()
Makefile | 2 +-
arch/x86/include/asm/insn.h | 15 +++++
arch/x86/kernel/uprobes.c | 10 ++--
arch/x86/lib/insn-eval.c | 5 +-
drivers/i2c/busses/i2c-imx.c | 42 +++++++++++---
drivers/i2c/busses/i2c-qup.c | 3 +-
drivers/input/serio/i8042.c | 3 +-
drivers/iommu/amd_iommu_types.h | 2 +-
drivers/md/dm-writecache.c | 4 +-
drivers/md/dm.c | 2 -
drivers/net/geneve.c | 20 ++-----
drivers/pinctrl/intel/pinctrl-baytrail.c | 67 ++++++++++++++++++-----
drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +-
drivers/spi/spi-bcm-qspi.c | 34 ++++--------
drivers/spi/spi-bcm2835.c | 22 +++-----
drivers/spi/spi.c | 58 +++++++++++++++++++-
drivers/usb/gadget/function/f_fs.c | 6 +-
drivers/usb/serial/ch341.c | 5 +-
drivers/usb/serial/kl5kusb105.c | 10 ++--
drivers/usb/serial/option.c | 10 ++--
fs/cifs/connect.c | 2 +
fs/gfs2/rgrp.c | 4 ++
include/linux/spi/spi.h | 19 +++++++
kernel/trace/ftrace.c | 22 +++++++-
kernel/trace/trace.c | 7 ++-
kernel/trace/trace.h | 6 +-
mm/list_lru.c | 10 ++--
mm/swapfile.c | 4 +-
net/netfilter/nf_tables_api.c | 3 +-
sound/pci/hda/hda_generic.c | 12 ++--
sound/pci/hda/hda_generic.h | 1 +
sound/pci/hda/patch_realtek.c | 6 ++
tools/objtool/arch/x86/include/asm/insn.h | 15 +++++
tools/perf/util/intel-pt-decoder/insn.h | 15 +++++
34 files changed, 329 insertions(+), 119 deletions(-)
--
2.25.1
1
38
14 Dec '20
From: Yang Xingui <yangxingui(a)huawei.com>
driver inclusion
category: bugfix
bugzilla: NA
CVE: NA
Call down() at RCU Read-Side Critical Secrion sometimes may
caugh a RCU preempt Calltrace.
[ 3506.800288] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
[ 3506.806357] rcu: Tasks blocked on level-1 rcu_node (CPUs 0-15): P22895/1:b..l
[ 3506.813556] (detected by 108, t=162805 jiffies, g=124209, q=59192378)
[ 3506.820056] kworker/0:1H D 0 22895 2 0x00000228
[ 3506.825524] Workqueue: kblockd blk_mq_run_work_fn
[ 3506.830207] Call trace:
[ 3506.832644] __switch_to+0xf0/0x140
[ 3506.836118] __schedule+0x890/0xdc8
[ 3506.839590] schedule+0x80/0x120
[ 3506.842804] schedule_timeout+0x22c/0x328
[ 3506.846796] __down+0x74/0xc8
[ 3506.849751] down+0x54/0x70
[ 3506.852539] hisi_sas_task_exec.isra.25+0x840/0xf28 [hisi_sas_main]
[ 3506.858780] hisi_sas_queue_command+0x40/0x84 [hisi_sas_main]
[ 3506.864502] sas_queuecommand+0x144/0x1c8 [libsas]
[ 3506.869271] scsi_queue_rq+0x72c/0xa20
[ 3506.873005] blk_mq_dispatch_rq_list+0x110/0x680
[ 3506.877601] blk_mq_do_dispatch_sched+0x108/0x148
[ 3506.882285] __blk_mq_sched_dispatch_requests+0x120/0x1b8
[ 3506.887659] blk_mq_sched_dispatch_requests+0x40/0x78
[ 3506.892688] __blk_mq_run_hw_queue+0xb8/0x138
[ 3506.897026] blk_mq_run_work_fn+0x28/0x38
Actually it's no need for keeping IO stopping here to wait for
controller reset complete. We can directly return error code.
Signed-off-by: Yang Xingui <yangxingui(a)huawei.com>
Reviewed-by: Zhu Xiongxiong <zhuxiongxiong(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/hisi_sas/hisi_sas_main.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 124aa26fa4b8..0128c547e4c8 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -611,19 +611,9 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
hisi_hba = dev_to_hisi_hba(device);
dev = hisi_hba->dev;
- if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) {
- /*
- * For IOs from upper layer, it may already disable preempt
- * in the IO path, if disable preempt again in down(),
- * function schedule() will report schedule_bug(), so check
- * preemptible() before goto down().
- */
- if (!preemptible())
- return -EINVAL;
+ if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
+ return -EINVAL;
- down(&hisi_hba->sem);
- up(&hisi_hba->sem);
- }
/* protect task_prep and start_delivery sequence */
rc = hisi_sas_task_prep(task, is_tmf, tmf, &pass, &dq);
--
2.25.1
1
4
[PATCH v2] arm64/mpam: Avoid compilation error of enable_acpi redefinition
by Wang ShaoBo 11 Dec '20
by Wang ShaoBo 11 Dec '20
11 Dec '20
hulk inclusion
category: bugfix
bugzilla: 46772
CVE: NA
Reference: https://gitee.com/openeuler/kernel/issues/I28HIY
-------------------------------------------------
enable_acpi is declaration as a enumerated type in mpam, where it's
also defined as a static inline function in acpi.h, this following
compilation error will be triggered if we use their two like this.
In file included from ./include/acpi/acpi_io.h:7:0,
from ./include/linux/acpi.h:47,
from ./arch/arm64/include/asm/machine_t.h:26,
from arch/arm64/kernel/process.c:64:
./arch/arm64/include/asm/acpi.h:82:20: error: ‘enable_acpi’ redeclared as different kind of symbol
static inline void enable_acpi(void)
^~~~~~~~~~~
In file included from arch/arm64/kernel/process.c:61:0:
./arch/arm64/include/asm/mpam_sched.h:46:2: note: previous definition of ‘enable_acpi’ was here
enable_acpi,
We should rename enable_acpi properly for mpam.
Reported-by: Zhengyuan Liu <liuzhengyuan(a)tj.kylinos.cn>
Signed-off-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
---
arch/arm64/include/asm/mpam_sched.h | 6 +++---
arch/arm64/kernel/mpam.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/mpam_sched.h b/arch/arm64/include/asm/mpam_sched.h
index 350296157087a..ddc7ce3e1a9e1 100644
--- a/arch/arm64/include/asm/mpam_sched.h
+++ b/arch/arm64/include/asm/mpam_sched.h
@@ -41,9 +41,9 @@ static inline void mpam_sched_in(void)
}
enum mpam_enable_type {
- enable_denied = 0,
- enable_default,
- enable_acpi,
+ MPAM_ENABLE_DENIED = 0,
+ MPAM_ENABLE_DEFAULT,
+ MPAM_ENABLE_ACPI,
};
extern enum mpam_enable_type __read_mostly mpam_enabled;
diff --git a/arch/arm64/kernel/mpam.c b/arch/arm64/kernel/mpam.c
index 3f89cec8e2fb1..96f4d013a9034 100644
--- a/arch/arm64/kernel/mpam.c
+++ b/arch/arm64/kernel/mpam.c
@@ -252,7 +252,7 @@ int __init mpam_force_init(void)
{
int ret;
- if (mpam_enabled != enable_default)
+ if (mpam_enabled != MPAM_ENABLE_DEFAULT)
return 0;
ret = mpam_nodes_discovery_start();
@@ -1380,9 +1380,9 @@ enum mpam_enable_type __read_mostly mpam_enabled;
static int __init mpam_setup(char *str)
{
if (!strcmp(str, "=acpi"))
- mpam_enabled = enable_acpi;
+ mpam_enabled = MPAM_ENABLE_ACPI;
else
- mpam_enabled = enable_default;
+ mpam_enabled = MPAM_ENABLE_DEFAULT;
return 1;
}
__setup("mpam", mpam_setup);
--
2.17.1
1
0
会议纪要:
与会人:Zheng Zhenpeng, xiexiuqi, dukaitian, myeuler, jiaoff, Liu Yuan, Wenlong.Ding, 潘晨博
1. 网迅万兆网卡驱动合入 openEuler 内核讨论 - 郑振鹏、刘源
>
> 网迅万兆网卡是国内具有完全知识产权的万兆网络控制器,相关资料请访问官方网站:
> 网卡成品及资料
> https://www.net-swift.com/a/383.html
> 网卡芯片
> https://www.net-swift.com/a/275.html
>
> 之前我们已向EulerOS发布版本提供万兆网卡驱动rpm包,此次希望能加深合作,
> 将驱动源码推入openeuler内核。
> 根据开源规则(遵从GPLV2),我厂已在官网上提供源码下载
1)openEuler 欢迎网讯网卡驱动合入社区,使 openEuler 支持更丰富的设备。
2)kernel sig 同意网讯万兆网卡驱动合入 openEuler,后续驱动可以按照开源
社区的规范,准备补丁;
- 建议合入openEuler 20.03 LTS SP2 (kernel-4.19),如果时间赶不上的话,
与 Release sig 讨论是否可以合入后续 update 版本;
- 该驱动代码量约 5w+ 行,首次合入时,不要求把所有开发历史作为补丁发出来,
可以按照模块或者功能做适当的补丁拆分;
3)建议加入到兼容性sig 组,兼容性 sig 与网讯网卡确认的认证过程
4)与 Release sig 对齐 Release 节奏
5)另有针对网讯网卡针对 dpdk 的适配,也欢迎参与 openEuler,贡献社区。
On 2020/12/10 9:32, zhenpengzheng(a)net-swift.com wrote:
> 收到,我会按时参加。
>
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> ****************************************************************
>
> 郑振鹏(zheng zhenpeng)
>
> 北京网迅科技有限公司杭州分公司 软件工程师
>
> 浙江省杭州市西湖区文三路478号华星时代广场A座507室 310013
>
> Beijing WangXun Technology Co., Ltd. Software Engineer.
>
> Room A507, HuaXing Times Square, No.478 West Wensan Road.
>
> West Lake District, Hangzhou City, 310013 ZHEJIANG, P.R.CHINA.
>
>
>
> Office: +86(0571)89807901-8014
>
> Mobile: +86-13656681762
>
> E-Mail: z <mailto:jianwang@trustnetic.com>henpengzheng(a)net-swift.com
>
> ****************************************************************
>
>
> *发件人:* Xie XiuQi <mailto:xiexiuqi@huawei.com>
> *发送时间:* 2020-12-09 20:09
> *收件人:* kernel(a)openeuler.org <mailto:kernel@openeuler.org>
> *抄送:* tc(a)openeuler.org <mailto:tc@openeuler.org>; dev(a)openeuler.org <mailto:dev@openeuler.org>; release(a)openeuler.org <mailto:release@openeuler.org>; 郑振鹏 <mailto:zhenpengzheng@net-swift.com>; Liuyuan (Compatibility, Cloud Infrastructure Service Product Dept.) <mailto:liuyuan36@huawei.com>
> *主题:* Re: [Release] Re: 【议题申报】 openEuler kernel sig meeting
> 议题:
>
> 1)网迅万兆网卡驱动合入 openEuler 内核讨论 - 郑振鹏、刘源
>
> 网迅万兆网卡是国内具有完全知识产权的万兆网络控制器,相关资料请访问官方网站:
> 网卡成品及资料
> https://www.net-swift.com/a/383.html
> 网卡芯片
> https://www.net-swift.com/a/275.html
>
> 之前我们已向EulerOS发布版本提供万兆网卡驱动rpm包,此次希望能加深合作,将驱动源码推入openeuler内核。
> 根据开源规则(遵从GPLV2),我厂已在官网上提供源码下载
>
>
> 欢迎继续申报议题
>
> On 2020/12/2 19:52, Xie XiuQi wrote:
> >
> >
> > On 2020/12/2 19:26, openEuler conference wrote:
> >> 您好!
> >>
> >> openEuler Kernel SIG 邀请您参加 2020-12-11 10:00 召开的ZOOM会议
> >>
> >> 会议主题:openEuler kernel sig meeting
> >>
> >> 会议链接:https://zoom.us/j/95008051399?pwd=RVRzNk0zSVUxdmVaaWZjT1d4UEhVQT09
> >>
> >> 更多资讯尽在:https://openeuler.org/zh/
> >>
> >>
> >>
> >> Hello!
> >>
> >> openEuler Kernel SIG invites you to attend the ZOOM conference will be held at 2020-12-11 10:00,
> >>
> >> The subject of the conference is openEuler kernel sig meeting,
> >>
> >> You can join the meeting at https://zoom.us/j/95008051399?pwd=RVRzNk0zSVUxdmVaaWZjT1d4UEhVQT09.
> >>
> >> More information <https://openeuler.org/zh/>
> >>
> >>
> >> _______________________________________________
> >> Release mailing list -- release(a)openeuler.org
> >> To unsubscribe send an email to release-leave(a)openeuler.org
> >>
> > _______________________________________________
> > Release mailing list -- release(a)openeuler.org
> > To unsubscribe send an email to release-leave(a)openeuler.org
> >
>
>
1
0
10 Dec '20
hulk inclusion
category: bugfix
bugzilla: 46772
CVE: NA
Reference: https://gitee.com/openeuler/kernel/issues/I28HIY
-------------------------------------------------
enable_acpi is declaration as a enumerated type in mpam, where it's
also defined as a static inline function in acpi.h, this following
compilation error will be triggered if we use their two like this.
In file included from ./include/acpi/acpi_io.h:7:0,
from ./include/linux/acpi.h:47,
from ./arch/arm64/include/asm/machine_t.h:26,
from arch/arm64/kernel/process.c:64:
./arch/arm64/include/asm/acpi.h:82:20: error: ‘enable_acpi’ redeclared as different kind of symbol
static inline void enable_acpi(void)
^~~~~~~~~~~
In file included from arch/arm64/kernel/process.c:61:0:
./arch/arm64/include/asm/mpam_sched.h:46:2: note: previous definition of ‘enable_acpi’ was here
enable_acpi,
We should rename enable_acpi properly for mpam.
Signed-off-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
---
arch/arm64/include/asm/mpam_sched.h | 6 +++---
arch/arm64/kernel/mpam.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/mpam_sched.h b/arch/arm64/include/asm/mpam_sched.h
index 350296157087a..ddc7ce3e1a9e1 100644
--- a/arch/arm64/include/asm/mpam_sched.h
+++ b/arch/arm64/include/asm/mpam_sched.h
@@ -41,9 +41,9 @@ static inline void mpam_sched_in(void)
}
enum mpam_enable_type {
- enable_denied = 0,
- enable_default,
- enable_acpi,
+ MPAM_ENABLE_DENIED = 0,
+ MPAM_ENABLE_DEFAULT,
+ MPAM_ENABLE_ACPI,
};
extern enum mpam_enable_type __read_mostly mpam_enabled;
diff --git a/arch/arm64/kernel/mpam.c b/arch/arm64/kernel/mpam.c
index 3f89cec8e2fb1..96f4d013a9034 100644
--- a/arch/arm64/kernel/mpam.c
+++ b/arch/arm64/kernel/mpam.c
@@ -252,7 +252,7 @@ int __init mpam_force_init(void)
{
int ret;
- if (mpam_enabled != enable_default)
+ if (mpam_enabled != MPAM_ENABLE_DEFAULT)
return 0;
ret = mpam_nodes_discovery_start();
@@ -1380,9 +1380,9 @@ enum mpam_enable_type __read_mostly mpam_enabled;
static int __init mpam_setup(char *str)
{
if (!strcmp(str, "=acpi"))
- mpam_enabled = enable_acpi;
+ mpam_enabled = MPAM_ENABLE_ACPI;
else
- mpam_enabled = enable_default;
+ mpam_enabled = MPAM_ENABLE_DEFAULT;
return 1;
}
__setup("mpam", mpam_setup);
--
2.17.1
2
1
Alexander Duyck (1):
tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
Anmol Karn (1):
rose: Fix Null pointer dereference in rose_send_frame()
Antoine Tenart (2):
netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING
traversal
net: ip6_gre: set dev->hard_header_len when using header_ops
Dan Carpenter (2):
net/x25: prevent a couple of overflows
chelsio/chtls: fix a double free in chtls_setkey()
Eran Ben Elisha (1):
net/mlx5: Fix wrong address reclaim when command interface is down
Eric Dumazet (1):
geneve: pull IP header before ECN decapsulation
Greg Kroah-Hartman (1):
Linux 4.19.162
Guillaume Nault (1):
ipv4: Fix tos mask in inet_rtm_getroute()
Hector Martin (1):
ALSA: usb-audio: US16x08: fix value count for level meters
Jamie Iles (1):
bonding: wait for sysfs kobject destruction before freeing struct
slave
Jens Axboe (1):
tun: honor IOCB_NOWAIT flag
Julian Wiedmann (1):
net/af_iucv: set correct sk_protocol for child sockets
Krzysztof Kozlowski (1):
dt-bindings: net: correct interrupt flags in examples
Lijun Pan (1):
ibmvnic: fix call_netdevice_notifiers in do_reset
Maxim Mikityanskiy (1):
net/tls: Protect from calling tls_dev_del for TLS RX twice
Po-Hsu Lin (1):
Input: i8042 - add ByteSpeed touchpad to noloop table
Sanjay Govind (1):
Input: xpad - support Ardwiino Controllers
Shiraz Saleem (1):
RDMA/i40iw: Address an mmap handler exploit in i40iw
Sylwester Dziedziuch (1):
i40e: Fix removing driver while bare-metal VFs pass traffic
Thomas Falcon (2):
ibmvnic: Ensure that SCRQ entry reads are correctly ordered
ibmvnic: Fix TX completion error handling
Vadim Fedorenko (1):
net/tls: missing received data after fast remote close
Vasily Averin (1):
tracing: Remove WARN_ON in start_thread()
Vinay Kumar Yadav (1):
chelsio/chtls: fix panic during unload reload chtls
Wang Hai (2):
ipv6: addrlabel: fix possible memory leak in ip6addrlbl_net_init
net: mvpp2: Fix error return code in mvpp2_open()
Willem de Bruijn (1):
sock: set sk_err to ee_errno on dequeue from errq
Yves-Alexis Perez (1):
usbnet: ipheth: fix connectivity with iOS 14
Zhang Changzhong (2):
cxgb3: fix error return code in t3_sge_alloc_qset()
net: pasemi: fix error return code in pasemi_mac_open()
.../devicetree/bindings/net/nfc/nxp-nci.txt | 2 +-
.../devicetree/bindings/net/nfc/pn544.txt | 2 +-
Makefile | 2 +-
drivers/crypto/chelsio/chtls/chtls_cm.c | 1 +
drivers/crypto/chelsio/chtls/chtls_hw.c | 1 +
drivers/infiniband/hw/i40iw/i40iw_main.c | 5 --
drivers/infiniband/hw/i40iw/i40iw_verbs.c | 36 +++--------
drivers/input/joystick/xpad.c | 2 +
drivers/input/serio/i8042-x86ia64io.h | 4 ++
drivers/net/bonding/bond_main.c | 61 +++++++++++++------
drivers/net/bonding/bond_sysfs_slave.c | 18 +-----
drivers/net/ethernet/chelsio/cxgb3/sge.c | 1 +
drivers/net/ethernet/ibm/ibmvnic.c | 26 ++++++--
drivers/net/ethernet/intel/i40e/i40e.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 22 ++++---
.../ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 ++++----
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 +
.../ethernet/mellanox/mlx5/core/pagealloc.c | 21 ++++++-
drivers/net/ethernet/pasemi/pasemi_mac.c | 8 ++-
drivers/net/geneve.c | 20 ++++--
drivers/net/tun.c | 14 ++++-
drivers/net/usb/ipheth.c | 2 +-
include/net/bonding.h | 8 +++
include/net/tls.h | 6 ++
kernel/trace/trace_hwlat.c | 2 +-
net/bridge/br_netfilter_hooks.c | 7 ++-
net/core/skbuff.c | 2 +-
net/ipv4/route.c | 7 ++-
net/ipv4/tcp_cong.c | 5 ++
net/ipv6/addrlabel.c | 26 +++++---
net/ipv6/ip6_gre.c | 16 ++++-
net/iucv/af_iucv.c | 4 +-
net/rose/rose_loopback.c | 17 ++++--
net/tls/tls_device.c | 5 +-
net/tls/tls_sw.c | 6 ++
net/x25/af_x25.c | 6 +-
sound/usb/mixer_us16x08.c | 2 +-
37 files changed, 260 insertions(+), 135 deletions(-)
--
2.25.1
1
32
From: Amir Goldstein <amir73il(a)gmail.com>
mainline inclusion
from mainline-5.7-rc1
commit 55bf882c7f13dda8bbe624040c6d5b4fbb812d16
category: bugfix
bugzilla: 46764
CVE: NA
https://gitee.com/openeuler/kernel/issues/I27PTB?from=project-issue
---------------------------
Change the logic of FAN_ONDIR in two ways that are similar to the logic
of FAN_EVENT_ON_CHILD, that was fixed in commit 54a307ba8d3c ("fanotify:
fix logic of events on child"):
1. The flag is meaningless in ignore mask
2. The flag refers only to events in the mask of the mark where it is set
This is what the fanotify_mark.2 man page says about FAN_ONDIR:
"Without this flag, only events for files are created." It doesn't
say anything about setting this flag in ignore mask to stop getting
events on directories nor can I think of any setup where this capability
would be useful.
Currently, when marks masks are merged, the FAN_ONDIR flag set in one
mark affects the events that are set in another mark's mask and this
behavior causes unexpected results. For example, a user adds a mark on a
directory with mask FAN_ATTRIB | FAN_ONDIR and a mount mark with mask
FAN_OPEN (without FAN_ONDIR). An opendir() of that directory (which is
inside that mount) generates a FAN_OPEN event even though neither of the
marks requested to get open events on directories.
Link: https://lore.kernel.org/r/20200319151022.31456-10-amir73il@gmail.com
Signed-off-by: Amir Goldstein <amir73il(a)gmail.com>
Signed-off-by: Jan Kara <jack(a)suse.cz>
Conflicts:
fs/notify/fanotify/fanotify.c
Signed-off-by: yangerkun <yangerkun(a)huawei.com>
Reviewed-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/notify/fanotify/fanotify.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index ca3405f73264..cdf0dc9ddbbb 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -117,6 +117,12 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
/* Apply ignore mask regardless of ISDIR and ON_CHILD flags */
marks_ignored_mask |= mark->ignored_mask;
+ /*
+ * If the event is on dir and this mark doesn't care about
+ * events on dir, don't send it!
+ */
+ if (d_is_dir(path->dentry) && !(mark->mask & FS_ISDIR))
+ continue;
/*
* If the event is for a child and this mark doesn't care about
@@ -130,10 +136,6 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
marks_mask |= mark->mask;
}
- if (d_is_dir(path->dentry) &&
- !(marks_mask & FS_ISDIR & ~marks_ignored_mask))
- return false;
-
if (event_mask & FAN_ALL_OUTGOING_EVENTS & marks_mask &
~marks_ignored_mask)
return true;
--
2.25.1
1
0
3
3
From: Tang Yizhou <tangyizhou(a)huawei.com>
ascend inclusion
category: bugfix
bugzilla: NA
CVE: NA
-------------------------------------------------
1. Error handling of sp_free().
2. When sp_alloc(..., SP_HUGEPAGE, ...) rollbacks to normal page, we need
to call vfs_fallocate() otherwise memory leaks until sp group is dead.
3. When sp_alloc(..., SP_HUGEPAGE, ...) rollbacks to normal page, we need
to clear SP_HUGEPAGE bit in sp_flags then spa_stat interface will show
the spa as a normal page spa correctly.
4. Add the reference count of a spg in find_or_alloc_sp_group() due to
closer relationship.
Signed-off-by: Tang Yizhou <tangyizhou(a)huawei.com>
Reviewed-by: Ding Tianhong <dingtianhong(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/share_pool.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/mm/share_pool.c b/mm/share_pool.c
index d39c2c3d728c..a71f6fb214ce 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -358,7 +358,7 @@ static struct sp_group *find_or_alloc_sp_group(int spg_id)
spg->hugepage_failures = 0;
spg->dvpp_multi_spaces = false;
spg->owner = current->group_leader;
- atomic_set(&spg->use_count, 0);
+ atomic_set(&spg->use_count, 1);
INIT_LIST_HEAD(&spg->procs);
INIT_LIST_HEAD(&spg->spa_list);
@@ -391,6 +391,10 @@ static struct sp_group *find_or_alloc_sp_group(int spg_id)
ret = PTR_ERR(spg->file_hugetlb);
goto out_fput;
}
+ } else {
+ if (!spg_valid(spg))
+ return ERR_PTR(-ENODEV);
+ atomic_inc(&spg->use_count);
}
return spg;
@@ -540,12 +544,6 @@ int sp_group_add_task(int pid, int spg_id)
goto out_put_task;
}
- if (!spg_valid(spg)) {
- ret = -ENODEV;
- goto out_put_task;
- }
- atomic_inc(&spg->use_count);
-
/* access control permission check */
if (sysctl_ac_mode == AC_SINGLE_OWNER) {
if (spg->owner != current->group_leader) {
@@ -1102,6 +1100,7 @@ int sp_free(unsigned long addr)
if (printk_ratelimit())
pr_err("share pool: sp free failed, addr %pK is not from sp_alloc\n",
(void *)addr);
+ goto drop_spa;
}
if (!spg_valid(spa->spg))
@@ -1312,31 +1311,32 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
__sp_free(spg, sp_addr, size_aligned,
list_next_entry(mm, sp_node));
+ if (printk_ratelimit())
+ pr_warn("share pool: allocation failed due to mm populate failed"
+ "(potential no enough memory when -12): %d\n", ret);
+ p = ERR_PTR(ret);
+
+ mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE;
+ offset = sp_addr - MMAP_SHARE_POOL_START;
+
+ ret = vfs_fallocate(spa_file(spa), mode, offset, spa_size(spa));
+ if (ret)
+ pr_err("share pool: sp alloc normal page fallocate failed %d\n", ret);
+
if (file == spg->file_hugetlb) {
spg->hugepage_failures++;
/* fallback to small pages */
if (!(sp_flags & SP_HUGEPAGE_ONLY)) {
file = spg->file;
- spa->is_hugepage = false;
size_aligned = ALIGN(size, PAGE_SIZE);
+ sp_flags &= ~SP_HUGEPAGE;
__sp_area_drop(spa);
mmput(mm);
goto try_again;
}
}
- if (printk_ratelimit())
- pr_warn("share pool: allocation failed due to mm populate failed"
- "(potential no enough memory when -12): %d\n", ret);
- p = ERR_PTR(ret);
-
- mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE;
- offset = sp_addr - MMAP_SHARE_POOL_START;
- ret = vfs_fallocate(spa_file(spa), mode, offset, spa_size(spa));
- if (ret)
- pr_err("share pool: fallocate failed %d\n", ret);
-
mmput(mm);
break;
}
--
2.25.1
1
16
[PATCH 1/7] ascend: share_pool: Use sharepool_no_page to alloc hugepage
by Yang Yingliang 08 Dec '20
by Yang Yingliang 08 Dec '20
08 Dec '20
From: Weilong Chen <chenweilong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
Sharepool applies for a dedicated interface for large pages,
which optimizes the efficiency of memory application
Reviewed-by: Ding Tianhong <dingtianhong(a)huawei.com>
Signed-off-by: Weilong Chen <chenweilong(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/hugetlb.h | 4 ++
include/linux/share_pool.h | 5 +++
mm/hugetlb.c | 22 +++++++---
mm/share_pool.c | 90 ++++++++++++++++++++++++++++++++++++++
4 files changed, 115 insertions(+), 6 deletions(-)
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index bd658f44e133..be649e5ba322 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -645,4 +645,8 @@ static inline spinlock_t *huge_pte_lock(struct hstate *h,
return ptl;
}
+#ifdef CONFIG_ASCEND_SHARE_POOL
+pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page, int writable);
+#endif
+
#endif /* _LINUX_HUGETLB_H */
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h
index 2557ef138122..47d8579c23ec 100644
--- a/include/linux/share_pool.h
+++ b/include/linux/share_pool.h
@@ -220,6 +220,11 @@ static inline void sp_dump_stack(void)
dump_stack();
}
+vm_fault_t sharepool_no_page(struct mm_struct *mm,
+ struct vm_area_struct *vma,
+ struct address_space *mapping, pgoff_t idx,
+ unsigned long address, pte_t *ptep, unsigned int flags);
+
#else
static inline int sp_group_add_task(int pid, int spg_id)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 9d2035632aed..a68e7e1afd82 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3352,8 +3352,13 @@ const struct vm_operations_struct hugetlb_vm_ops = {
.pagesize = hugetlb_vm_op_pagesize,
};
+#ifdef CONFIG_ASCEND_SHARE_POOL
+pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
+ int writable)
+#else
static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
int writable)
+#endif
{
pte_t entry;
@@ -3370,6 +3375,9 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
return entry;
}
+#ifdef CONFIG_ASCEND_SHARE_POOL
+EXPORT_SYMBOL(make_huge_pte);
+#endif
static void set_huge_ptep_writable(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
@@ -3962,12 +3970,6 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
}
page = alloc_huge_page(vma, haddr, 0);
- if (IS_ERR(page) && sp_check_vm_share_pool(vma->vm_flags)) {
- page = alloc_huge_page_node(hstate_file(vma->vm_file),
- numa_mem_id());
- if (!page)
- page = ERR_PTR(-ENOMEM);
- }
if (IS_ERR(page)) {
/*
* Returning error will result in faulting task being
@@ -4155,7 +4157,15 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
entry = huge_ptep_get(ptep);
if (huge_pte_none(entry)) {
+#ifdef CONFIG_ASCEND_SHARE_POOL
+ if (sp_check_vm_share_pool(vma->vm_flags)) {
+ ret = sharepool_no_page(mm, vma, mapping, idx, address, ptep, flags);
+ } else {
+ ret = hugetlb_no_page(mm, vma, mapping, idx, address, ptep, flags);
+ }
+#else
ret = hugetlb_no_page(mm, vma, mapping, idx, address, ptep, flags);
+#endif
goto out_mutex;
}
diff --git a/mm/share_pool.c b/mm/share_pool.c
index 23195a76c2c6..286e74f99360 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -41,6 +41,8 @@
#include <linux/idr.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/rmap.h>
+#include <linux/hugetlb.h>
/* access control mode macros */
#define AC_NONE 0
@@ -2399,6 +2401,94 @@ static int spa_stat_show(struct seq_file *seq, void *offset)
return 0;
}
+vm_fault_t sharepool_no_page(struct mm_struct *mm,
+ struct vm_area_struct *vma,
+ struct address_space *mapping, pgoff_t idx,
+ unsigned long address, pte_t *ptep, unsigned int flags)
+{
+ struct hstate *h = hstate_vma(vma);
+ vm_fault_t ret = VM_FAULT_SIGBUS;
+ unsigned long size;
+ struct page *page;
+ pte_t new_pte;
+ spinlock_t *ptl;
+ unsigned long haddr = address & huge_page_mask(h);
+ bool new_page = false;
+ int err;
+
+retry:
+ page = find_lock_page(mapping, idx);
+ if (!page) {
+ size = i_size_read(mapping->host) >> huge_page_shift(h);
+ if (idx >= size)
+ goto out;
+
+ page = alloc_huge_page(vma, haddr, 0);
+ if (IS_ERR(page)) {
+ page = alloc_huge_page_node(hstate_file(vma->vm_file),
+ numa_mem_id());
+ if (!page)
+ page = ERR_PTR(-ENOMEM);
+ }
+ if (IS_ERR(page)) {
+ ptl = huge_pte_lock(h, mm, ptep);
+ if (!huge_pte_none(huge_ptep_get(ptep))) {
+ ret = 0;
+ spin_unlock(ptl);
+ goto out;
+ }
+ spin_unlock(ptl);
+ ret = vmf_error(PTR_ERR(page));
+ goto out;
+ }
+ __SetPageUptodate(page);
+ new_page = true;
+
+ /* sharepool pages are all shared */
+ err = huge_add_to_page_cache(page, mapping, idx);
+ if (err) {
+ put_page(page);
+ if (err == -EEXIST)
+ goto retry;
+ goto out;
+ }
+ }
+
+
+ ptl = huge_pte_lock(h, mm, ptep);
+ size = i_size_read(mapping->host) >> huge_page_shift(h);
+ if (idx >= size)
+ goto backout;
+
+ ret = 0;
+ if (!huge_pte_none(huge_ptep_get(ptep)))
+ goto backout;
+
+ page_dup_rmap(page, true);
+ new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
+ && (vma->vm_flags & VM_SHARED)));
+ set_huge_pte_at(mm, haddr, ptep, new_pte);
+
+ hugetlb_count_add(pages_per_huge_page(h), mm);
+
+ spin_unlock(ptl);
+
+ if (new_page) {
+ SetPagePrivate(&page[1]);
+ }
+
+ unlock_page(page);
+out:
+ return ret;
+
+backout:
+ spin_unlock(ptl);
+ unlock_page(page);
+ put_page(page);
+ goto out;
+}
+EXPORT_SYMBOL(sharepool_no_page);
+
/*
* Called by proc_root_init() to initialize the /proc/sharepool subtree
*/
--
2.25.1
1
6
Building the latest 2003 LTS can trigger following compilation error:
In file included from ./include/acpi/acpi_io.h:7:0,
from ./include/linux/acpi.h:47,
from ./arch/arm64/include/asm/machine_t.h:26,
from arch/arm64/kernel/process.c:64:
./arch/arm64/include/asm/acpi.h:82:20: error: ‘enable_acpi’ redeclared as different kind of symbol
static inline void enable_acpi(void)
^~~~~~~~~~~
In file included from arch/arm64/kernel/process.c:61:0:
./arch/arm64/include/asm/mpam_sched.h:46:2: note: previous definition of ‘enable_acpi’ was here
enable_acpi,
The redefinition was introduced by commit 7e66740ad725
("MPAM / ACPI: Refactoring MPAM init process and set MPAM ACPI as entrance")
2
2
各位社区内的开发者:
openEuler Summit 所有议程 <https://openeuler.org/zh/interaction/summit-list/>
本周已经全部上线。本次峰会设置了 Linux 操作系统、云与云原生、虚拟化、基础软件、开源基础设施、安全与可信六大专场。一些通过 Call for
Speaker 提交的议题已经入选。欢迎大家快来围观有没有你感兴趣的议题。
[image: image.png]
针对社区的开发者,我们准备了很多专属环节:
1. 大会为社区开发者准备了专属报名通道,在现场有专属的签到通道和定制的伴手礼。
2. 大会为Maintainer 准备了一份十分具有荣誉感和纪念意义的徽章。
大会现场还准备了惊喜环节:
大会主题演讲时会通过报名时你填写的 Gitee ID 和Gitee 后台的数据演示一个非常炫酷的Live Demo。
我们诚挚地邀请社区开发者到现场参会。
社区开发者专属报名通道:https://etherpad.openeuler.org/p/openEuler-Summit-2020
P.S:通过该链接报名的人员可以参加 Day1和 Day2 两天会议。
openEuler 也将迎来自己的一周岁生日,社区准备了一个“我为 openEuler 代言”的百人视频合集,诚挚地邀请所有热爱openEuler
的人来拍摄一段视频,来纪念openEuler这朝气蓬勃的第一年。
“我为 openEuler 代言”的视频拍摄需求:
自拍形式,对着镜头回答以下问题:
1. 我想要的操作系统是****的,
2. 我在**时候参与/认识/加入/知道的openEuler(社区)
3. 我在openEuler贡献了****
4. 我是***,我为openEuler代言
使用场景:
您拍摄的视频素材将用于 openEuler Summit 2020 前期的会议宣传和开场视频中。
拍摄指导:
1. 背景任您喜欢
2. 人物面对镜头,位于画面中央,取半身构图,横向拍摄16:9 的画面比例
3. 最好选择白炽灯,白色光源
4. 尽量由另一个人辅助,用手机后置摄像头拍摄,不要用前置,拍摄前擦拭摄像头
5. 读口播时,声音越大越好
6. 尽量保证每一句话都是完整通顺的,中间重来的部分可以忽略
7. 视频输出,用电脑将手机视频导出,打压缩包传输即可(不要用微信上传,会压缩画质)
8. 拍摄完毕后请将视频上传到百度网盘,将分享链接期限设置为永久,然后发给 public(a)openeuler.io
9. 视频收集截止日期:2020年12月11日23:59分
1
0
Alan Stern (2):
USB: core: Change %pK for __user pointers to %px
USB: core: Fix regression in Hercules audio card
Anand K Mistry (1):
x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb
Ard Biesheuvel (1):
efivarfs: revert "fix memory leak in efivarfs_create()"
Benjamin Berg (1):
platform/x86: thinkpad_acpi: Send tablet mode switch at wakeup time
Brian Masney (1):
x86/xen: don't unbind uninitialized lock_kicker_irq
Chris Ye (1):
HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
Cong Wang (1):
netfilter: clear skb->next in NF_HOOK_LIST()
Dexuan Cui (1):
video: hyperv_fb: Fix the cache type when mapping the VRAM
Filipe Manana (1):
btrfs: fix lockdep splat when reading qgroup config on mount
Frank Yang (1):
HID: cypress: Support Varmilo Keyboards' media hotkeys
Greg Kroah-Hartman (1):
Linux 4.19.161
Hans de Goede (2):
Input: i8042 - allow insmod to succeed on devices without an i8042
controller
HID: Add Logitech Dinovo Edge battery quirk
Hauke Mehrtens (1):
wireless: Use linux/stddef.h instead of stddef.h
Igor Lubashev (1):
perf event: Check ref_reloc_sym before using it
Jens Axboe (1):
proc: don't allow async path resolution of /proc/self components
Jiri Kosina (1):
HID: add support for Sega Saturn
Johannes Thumshirn (1):
btrfs: don't access possibly stale fs_info data for printing duplicate
device
Julian Wiedmann (1):
s390/qeth: fix tear down of async TX buffers
Kai Vehmanen (1):
ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close
Kaixu Xia (1):
platform/x86: toshiba_acpi: Fix the wrong variable assignment
Krzysztof Kozlowski (1):
nfc: s3fwrn5: use signed integer for parsing GPIO numbers
Laurent Pinchart (1):
xtensa: uaccess: Add missing __user to strncpy_from_user() prototype
Lee Duncan (1):
scsi: libiscsi: Fix NOP race condition
Lijun Pan (2):
ibmvnic: fix NULL pointer dereference in reset_sub_crq_queues
ibmvnic: fix NULL pointer dereference in ibmvic_reset_crq
Lyude Paul (1):
drm/atomic_helper: Stop modesets on unregistered connectors harder
Marc Ferland (1):
dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
Marc Kleine-Budde (3):
ARM: dts: dra76x: m_can: fix order of clocks
can: gs_usb: fix endianess problem with candleLight firmware
can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
Marc Zyngier (1):
phy: tegra: xusb: Fix dangling pointer on probe failure
Masami Hiramatsu (1):
perf probe: Fix to die_entrypc() returns error correctly
Michael Chan (1):
bnxt_en: Release PCI regions when DMA mask setup fails during probe.
Mike Christie (1):
scsi: target: iscsi: Fix cmd abort fabric stop race
Minwoo Im (1):
nvme: free sq/cq dbbuf pointers when dbbuf set fails
Pablo Ceballos (1):
HID: hid-sensor-hub: Fix issue with devices with no report ID
Paolo Bonzini (2):
KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
KVM: x86: Fix split-irqchip vs interrupt injection window request
Raju Rangoju (1):
cxgb4: fix the panic caused by non smac rewrite
Rui Miguel Silva (1):
optee: add writeback to valid memory type
Sami Tolvanen (1):
perf/x86: fix sysfs type mismatches
Shay Agroskin (1):
net: ena: set initial DMA width to avoid intel iommu issue
Stanley Chu (1):
scsi: ufs: Fix race between shutdown and runtime resume flow
Sugar Zhang (1):
dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
Taehee Yoo (1):
batman-adv: set .owner to THIS_MODULE
Will Deacon (2):
arm64: pgtable: Fix pte_accessible()
arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
Xiaochen Shen (2):
x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount
leak
x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak
Xiongfeng Wang (1):
IB/mthca: fix return value of error branch in mthca_init_cq()
Zenghui Yu (1):
KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for
userspace
Zhang Changzhong (2):
bnxt_en: fix error return code in bnxt_init_one()
bnxt_en: fix error return code in bnxt_init_board()
Zhang Qilong (2):
usb: gadget: f_midi: Fix memleak in f_midi_alloc
usb: gadget: Fix memleak in gadgetfs_fill_super
penghao (1):
USB: quirks: Add USB_QUIRK_DISCONNECT_SUSPEND quirk for Lenovo A630Z
TIO built-in usb-audio card
Makefile | 2 +-
arch/arm/boot/dts/dra76x.dtsi | 4 +-
arch/arm64/include/asm/pgtable.h | 34 ++---
arch/x86/events/intel/cstate.c | 6 +-
arch/x86/events/intel/rapl.c | 14 +-
arch/x86/events/intel/uncore.c | 4 +-
arch/x86/events/intel/uncore.h | 12 +-
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kernel/cpu/bugs.c | 4 +-
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 65 ++++-----
arch/x86/kvm/irq.c | 85 +++++-------
arch/x86/kvm/lapic.c | 2 +-
arch/x86/kvm/x86.c | 18 +--
arch/x86/xen/spinlock.c | 12 +-
arch/xtensa/include/asm/uaccess.h | 2 +-
drivers/dma/pl330.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 4 +-
drivers/gpu/drm/drm_atomic.c | 21 ---
drivers/gpu/drm/drm_atomic_helper.c | 21 ++-
drivers/gpu/drm/drm_connector.c | 11 +-
drivers/gpu/drm/i915/intel_dp_mst.c | 8 +-
drivers/hid/hid-cypress.c | 44 +++++-
drivers/hid/hid-ids.h | 8 ++
drivers/hid/hid-input.c | 3 +
drivers/hid/hid-quirks.c | 5 +
drivers/hid/hid-sensor-hub.c | 3 +-
drivers/infiniband/hw/mthca/mthca_cq.c | 10 +-
drivers/input/serio/i8042.c | 12 +-
drivers/net/can/m_can/m_can.c | 2 +-
drivers/net/can/usb/gs_usb.c | 131 ++++++++++--------
drivers/net/ethernet/amazon/ena/ena_netdev.c | 17 ++-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 +-
.../net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 3 +-
drivers/net/ethernet/ibm/ibmvnic.c | 6 +
drivers/nfc/s3fwrn5/i2c.c | 4 +-
drivers/nvme/host/pci.c | 15 ++
drivers/phy/tegra/xusb.c | 1 +
drivers/platform/x86/thinkpad_acpi.c | 1 +
drivers/platform/x86/toshiba_acpi.c | 3 +-
drivers/s390/net/qeth_core_main.c | 6 -
drivers/scsi/libiscsi.c | 23 +--
drivers/scsi/ufs/ufshcd.c | 6 +-
drivers/target/iscsi/iscsi_target.c | 17 ++-
drivers/tee/optee/call.c | 3 +-
drivers/usb/core/devio.c | 14 +-
drivers/usb/core/quirks.c | 10 ++
drivers/usb/gadget/function/f_midi.c | 10 +-
drivers/usb/gadget/legacy/inode.c | 3 +
drivers/video/fbdev/hyperv_fb.c | 7 +-
fs/btrfs/qgroup.c | 2 +-
fs/btrfs/volumes.c | 8 +-
fs/efivarfs/inode.c | 2 +
fs/efivarfs/super.c | 1 -
fs/proc/self.c | 7 +
include/drm/drm_connector.h | 71 +++++++++-
include/linux/netfilter.h | 2 +-
include/scsi/libiscsi.h | 3 +
include/uapi/linux/wireless.h | 6 +-
net/batman-adv/log.c | 1 +
sound/pci/hda/patch_hdmi.c | 20 +--
tools/perf/util/dwarf-aux.c | 8 ++
tools/perf/util/event.c | 7 +-
virt/kvm/arm/vgic/vgic-mmio-v3.c | 22 ++-
63 files changed, 540 insertions(+), 323 deletions(-)
--
2.25.1
1
49
02 Dec '20
Al Viro (1):
don't dump the threads that had been already exiting when zapped.
Aleksandr Nogikh (1):
netem: fix zero division in tabledist
Andy Shevchenko (2):
device property: Keep secondary firmware node secondary by type
device property: Don't clear secondary pointer for shared primary
firmware node
Arjun Roy (1):
tcp: Prevent low rmem stalls with SO_RCVLOWAT.
Arnaldo Carvalho de Melo (1):
perf scripting python: Avoid declaring function pointers with a
visibility attribute
Boris Protopopov (1):
Convert trailing spaces and periods in path components
Brian Foster (1):
xfs: flush new eof page on truncate to avoid post-eof corruption
Chen Zhou (1):
selinux: Fix error return code in sel_ib_pkey_sid_slow()
Christoph Hellwig (2):
nbd: fix a block_device refcount leak in nbd_release
xfs: fix a missing unlock on error in xfs_fs_map_blocks
Chunyan Zhang (1):
tick/common: Touch watchdog in tick_unfreeze() on all CPUs
Dan Carpenter (1):
futex: Don't enable IRQs unconditionally in put_pi_state()
Darrick J. Wong (12):
xfs: fix realtime bitmap/summary file truncation when growing rt
volume
xfs: don't free rt blocks when we're doing a REMAP bunmapi call
xfs: set xefi_discard when creating a deferred agfl free log intent
item
xfs: fix scrub flagging rtinherit even if there is no rt device
xfs: fix flags argument to rmap lookup when converting shared file
rmaps
xfs: set the unwritten bit in rmap lookup flags in
xchk_bmap_get_rmapextents
xfs: fix rmap key and record comparison functions
xfs: fix brainos in the refcount scrubber's rmap fragment processor
vfs: remove lockdep bogosity in __sb_start_write
xfs: fix the minrecs logic when dealing with inode root child blocks
xfs: strengthen rmap record flags checking
xfs: revert "xfs: fix rmap key and record comparison functions"
Dinghao Liu (1):
ext4: fix error handling code in add_new_gdb
Dongli Zhang (1):
page_frag: Recover from memory pressure
Douglas Gilbert (1):
sgl_alloc_order: fix memory leak
Eddy Wu (1):
fork: fix copy_process(CLONE_PARENT) race with the exiting
->real_parent
Eric Biggers (1):
ext4: fix leaking sysfs kobject after failed mount
Gabriel Krisman Bertazi (2):
blk-cgroup: Fix memleak on error path
blk-cgroup: Pre-allocate tree node on blkg_conf_prep
George Spelvin (1):
random32: make prandom_u32() output unpredictable
Gerald Schaefer (1):
mm/userfaultfd: do not access vma->vm_mm after calling
handle_userfault()
Heiner Kallweit (1):
net: bridge: add missing counters to ndo_get_stats64 callback
Jan Kara (2):
ext4: Detect already used quota file early
ext4: fix bogus warning in ext4_update_dx_flag()
Jason A. Donenfeld (1):
netfilter: use actual socket sk rather than skb sk when routing harder
Jiri Olsa (2):
perf python scripting: Fix printable strings in python3 scripts
perf tools: Add missing swap for ino_generation
Jonathan Cameron (1):
ACPI: Add out of bounds and numa_off protections to pxm_to_node()
Joseph Qi (1):
ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
Kaixu Xia (1):
ext4: correctly report "not supported" for {usr, grp}jquota when
!CONFIG_QUOTA
Lang Dai (1):
uio: free uio id after uio file node is freed
Lee Jones (1):
Fonts: Replace discarded const qualifier
Leo Yan (1):
perf lock: Don't free "lock_seq_stat" if read_count isn't zero
Luo Meng (2):
ext4: fix invalid inode checksum
fail_function: Remove a redundant mutex unlock
Mao Wenan (1):
net: Update window_clamp if SOCK_RCVBUF is set
Marc Zyngier (1):
arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
Mateusz Nosek (1):
futex: Fix incorrect should_fail_futex() handling
Matteo Croce (2):
Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
reboot: fix overflow parsing reboot cpu number
Michael Schaller (1):
efivarfs: Replace invalid slashes with exclamation marks in dentries.
Mike Galbraith (1):
futex: Handle transient "ownerless" rtmutex state correctly
Miklos Szeredi (1):
fuse: fix page dereference after free
Ming Lei (1):
scsi: core: Don't start concurrent async scan on same host
Nicholas Piggin (1):
mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
Oleg Nesterov (1):
ptrace: fix task_join_group_stop() for the case when current is traced
Oliver Herms (1):
IPv6: Set SIT tunnel hard_header_len to zero
Peter Zijlstra (2):
serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
perf: Fix get_recursion_context()
Qiujun Huang (2):
ring-buffer: Return 0 on success from ring_buffer_resize()
tracing: Fix out of bounds write in get_trace_buf
Ronnie Sahlberg (1):
cifs: handle -EINTR in cifs_setattr
Ryan Sharpelletti (1):
tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
Shijie Luo (1):
mm: mempolicy: fix potential pte_unmap_unlock pte error
Shin'ichiro Kawasaki (1):
uio: Fix use-after-free in uio_unregister_device()
Stefano Brivio (1):
netfilter: ipset: Update byte and packet counters regardless of
whether they match
Steven Rostedt (VMware) (3):
ring-buffer: Fix recursion protection transitions between interrupt
context
ftrace: Fix recursion check for NMI test
ftrace: Handle tracing when switching between context
Tyler Hicks (1):
tpm: efi: Don't create binary_bios_measurements file for an empty log
Valentin Schneider (1):
arm64: topology: Stop using MPIDR for topology information
Vamshi K Sthambamkadi (1):
efivarfs: fix memory leak in efivarfs_create()
Wang Hai (2):
devlink: Add missing genlmsg_cancel() in
devlink_nl_sb_port_pool_fill()
inet_diag: Fix error path to cancel the meseage in
inet_req_diag_fill()
Wengang Wang (1):
ocfs2: initialize ip_next_orphan
Will Deacon (1):
arm64: psci: Avoid printing in cpu_psci_cpu_die()
Xiubo Li (1):
nbd: make the config put is called before the notifying the waiter
Yi-Hung Wei (1):
ip_tunnels: Set tunnel option flag when tunnel metadata is present
Yicong Yang (1):
libfs: fix error cast of negative value in simple_attr_write()
Yunsheng Lin (1):
net: sch_generic: fix the missing new qdisc assignment bug
Zeng Tao (1):
time: Prevent undefined behaviour in timespec64_to_ns()
Zhengyuan Liu (1):
arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
Zqiang (1):
kthread_worker: prevent queuing delayed work from timer_fn when it is
being canceled
zhuoliang zhang (1):
net: xfrm: fix a race condition during allocing spi
arch/Kconfig | 7 +
arch/arm64/include/asm/numa.h | 3 +
arch/arm64/kernel/cpu_errata.c | 8 +
arch/arm64/kernel/psci.c | 5 +-
arch/arm64/kernel/topology.c | 43 +-
arch/arm64/mm/numa.c | 6 +-
block/blk-cgroup.c | 15 +-
drivers/acpi/numa.c | 2 +-
drivers/base/core.c | 4 +-
drivers/block/nbd.c | 3 +-
drivers/char/random.c | 1 -
drivers/char/tpm/eventlog/efi.c | 5 +
drivers/net/geneve.c | 3 +-
drivers/scsi/scsi_scan.c | 7 +-
drivers/tty/serial/amba-pl011.c | 11 +-
drivers/uio/uio.c | 12 +-
fs/cifs/cifs_unicode.c | 8 +-
fs/cifs/inode.c | 13 +-
fs/efivarfs/super.c | 4 +
fs/exec.c | 15 +-
fs/ext4/ext4.h | 3 +-
fs/ext4/inline.c | 1 +
fs/ext4/inode.c | 11 +-
fs/ext4/resize.c | 4 +-
fs/ext4/super.c | 10 +-
fs/fuse/dev.c | 28 +-
fs/libfs.c | 6 +-
fs/ocfs2/super.c | 1 +
fs/super.c | 33 +-
fs/xfs/libxfs/xfs_alloc.c | 1 +
fs/xfs/libxfs/xfs_bmap.c | 19 +-
fs/xfs/libxfs/xfs_bmap.h | 2 +-
fs/xfs/libxfs/xfs_rmap.c | 2 +-
fs/xfs/scrub/bmap.c | 10 +-
fs/xfs/scrub/btree.c | 45 +-
fs/xfs/scrub/inode.c | 3 +-
fs/xfs/scrub/refcount.c | 8 +-
fs/xfs/xfs_iops.c | 10 +
fs/xfs/xfs_pnfs.c | 2 +-
fs/xfs/xfs_rtalloc.c | 10 +-
include/linux/netfilter_ipv4.h | 2 +-
include/linux/netfilter_ipv6.h | 2 +-
include/linux/prandom.h | 36 +-
include/linux/time64.h | 4 +
include/net/ip_tunnels.h | 7 +-
kernel/events/internal.h | 2 +-
kernel/exit.c | 5 +-
kernel/fail_function.c | 5 +-
kernel/fork.c | 10 +-
kernel/futex.c | 25 +-
kernel/kthread.c | 3 +-
kernel/reboot.c | 28 +-
kernel/signal.c | 19 +-
kernel/time/itimer.c | 4 -
kernel/time/tick-common.c | 2 +
kernel/time/timer.c | 7 -
kernel/trace/ring_buffer.c | 66 ++-
kernel/trace/trace.c | 2 +-
kernel/trace/trace.h | 26 +-
kernel/trace/trace_selftest.c | 9 +-
lib/fonts/font_10x18.c | 2 +-
lib/fonts/font_6x10.c | 2 +-
lib/fonts/font_6x11.c | 2 +-
lib/fonts/font_7x14.c | 2 +-
lib/fonts/font_8x16.c | 2 +-
lib/fonts/font_8x8.c | 2 +-
lib/fonts/font_acorn_8x8.c | 2 +-
lib/fonts/font_mini_4x6.c | 2 +-
lib/fonts/font_pearl_8x8.c | 2 +-
lib/fonts/font_sun12x22.c | 2 +-
lib/fonts/font_sun8x16.c | 2 +-
lib/random32.c | 462 +++++++++++-------
lib/scatterlist.c | 2 +-
mm/huge_memory.c | 9 +-
mm/mempolicy.c | 6 +-
mm/page_alloc.c | 5 +
net/bridge/br_device.c | 1 +
net/core/devlink.c | 6 +-
net/ipv4/inet_diag.c | 4 +-
net/ipv4/netfilter.c | 12 +-
net/ipv4/netfilter/ipt_SYNPROXY.c | 2 +-
net/ipv4/netfilter/iptable_mangle.c | 2 +-
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 2 +-
net/ipv4/netfilter/nf_reject_ipv4.c | 2 +-
net/ipv4/netfilter/nft_chain_route_ipv4.c | 2 +-
net/ipv4/syncookies.c | 9 +-
net/ipv4/tcp.c | 2 +
net/ipv4/tcp_bbr.c | 2 +-
net/ipv4/tcp_input.c | 3 +-
net/ipv6/netfilter.c | 6 +-
net/ipv6/netfilter/ip6table_mangle.c | 2 +-
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 2 +-
net/ipv6/netfilter/nft_chain_route_ipv6.c | 2 +-
net/ipv6/sit.c | 2 -
net/ipv6/syncookies.c | 10 +-
net/netfilter/ipset/ip_set_core.c | 3 +-
net/netfilter/ipvs/ip_vs_core.c | 4 +-
net/sched/sch_generic.c | 3 +
net/sched/sch_netem.c | 9 +-
net/xfrm/xfrm_state.c | 8 +-
security/selinux/ibpkey.c | 4 +-
tools/perf/builtin-lock.c | 2 +-
tools/perf/util/print_binary.c | 2 +-
.../scripting-engines/trace-event-python.c | 7 +-
tools/perf/util/session.c | 1 +
105 files changed, 809 insertions(+), 461 deletions(-)
--
2.25.1
1
87
Hi,
On 2020/12/2 11:12, Zhengyuan Liu wrote:
>
>
> On 2020/12/2 上午10:59, Yang Yingliang wrote:
>>
>> On 2020/12/2 10:47, Zhengyuan Liu wrote:
>>> Hi, Xiuqi
>>>
>>> 最近在 backport OpenEuler内核补丁时对于补丁来源有个疑问,每个Patch 来源类别都在
>>> commit log 里面标注了,如 mainline inclusion, stable inclusion, 这两 个比较好理解.但是像:
>>> hulk
>>> ascend
>>> driver
>>> euleros
>>> 这几个我查阅openeuler开发文档也没找到说明, 所以想请问下你们这几个是 怎么做区分的.
>>> 这个开发者在向openeuler社区提补丁时也用得到,方便的话麻烦你们更新到文 档里去.
这个确实是存在一些问题,这个 tag 的划分,既没有覆盖全,划分的标准也不完全一致。
当前是给的比较主观的一些 tag,既有按领域的,也有按来源的,也有按子系统的。
总之目的是为了方便识别和统计。
下面表格是我准备发到社区讨论的,也请大家帮忙看看。
| 补丁 tag | 说明 |
| ------------------- | ----------------------------------- |
| mainline inclusion | 主线 backport |
| stable inclusion | 上游 stable 分支的补丁 |
| maillist inclusion | 发到社区,但是还没进主线的补丁 |
| hulk inclusion | openEuler kernel 团队开发的补丁 |
| virt inclusion | 虚拟化相关的补丁 |
| ascend inclusion | 昇腾相关的补丁或特性 |
| kunpeng inclusion | 鲲鹏相关的补丁或特性 |
| dist inclusion | 从其他发行版移植的补丁 |
| openEuler inclusion | 其他发送到openEuler社区的非上游补丁 |
>>
>> 非主线的补丁会用到上面的分类,只要补丁是来自主线的统一用mainline
>>
>> ascend是支持昇腾芯片的一些特有补丁
>>
>> driver是驱动补丁
>>
>> euleros和hulk是一类,主要是一些未进主线的或者待进主线的通用补丁
>
> 感谢回复.
>
> driver相当于从hulk一类单独挑出来的是吧.从现有的分类来看,好像也没有严格的区分.
>
>
>>
>>
>>>
>>> 谢谢.
>>> _______________________________________________
>>> Kernel mailing list -- kernel(a)openeuler.org
>>> To unsubscribe send an email to kernel-leave(a)openeuler.org
>>
>
>
1
0
Hi, Xiuqi
最近在 backport OpenEuler内核补丁时对于补丁来源有个疑问,每个Patch 来源类别都在
commit log 里面标注了,如 mainline inclusion, stable inclusion, 这两个比较好理解.但是像:
hulk
ascend
driver
euleros
这几个我查阅openeuler开发文档也没找到说明, 所以想请问下你们这几个是怎么做区分的.
这个开发者在向openeuler社区提补丁时也用得到,方便的话麻烦你们更新到文档里去.
谢谢.
3
3
02 Dec '20
From: Vincent Bernat <vincent(a)bernat.ch>
mainline inclusion
from mainline-5.5-rc5
commit 07a4ddec3ce9b0a533b5f90f582f1057390d5e63
category: bugfix
issue: I27SUX
bugzilla: NA
------------------------------
Currently, gratuitous ARP/ND packets are sent every `miimon'
milliseconds. This commit allows a user to specify a custom delay
through a new option, `peer_notif_delay'.
Like for `updelay' and `downdelay', this delay should be a multiple of
`miimon' to avoid managing an additional work queue. The configuration
logic is copied from `updelay' and `downdelay'. However, the default
value cannot be set using a module parameter: Netlink or sysfs should
be used to configure this feature.
When setting `miimon' to 100 and `peer_notif_delay' to 500, we can
observe the 500 ms delay is respected:
20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28
In bond_mii_monitor(), I have tried to keep the lock logic readable.
The change is due to the fact we cannot rely on a notification to
lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is
only triggered once every N times, while we need to decrement the
counter each time.
iproute2 also needs to be updated to be able to specify this new
attribute through `ip link'.
Signed-off-by: Vincent Bernat <vincent(a)bernat.ch>
Signed-off-by: David S. Miller <davem(a)davemloft.net>
Signed-off-by: wangli <wangli221(a)huawei.com>
Signed-off-by: Aichun Li <liaichun(a)huawei.com>
---
drivers/net/bonding/bond_main.c | 31 +--
drivers/net/bonding/bond_netlink.c | 14 ++
drivers/net/bonding/bond_options.c | 75 +++++---
drivers/net/bonding/bond_procfs.c | 3 +-
drivers/net/bonding/bond_sysfs.c | 13 ++
include/net/bond_options.h | 1 +
include/net/bonding.h | 3 +-
include/uapi/linux/if_link.h | 1 +
tools/include/uapi/linux/if_link.h | 1 +
9 files changed, 102 insertions(+), 40 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a59333b..b1f3520 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -786,6 +786,8 @@ static bool bond_should_notify_peers(struct bonding *bond)
slave ? slave->dev->name : "NULL");
if (!slave || !bond->send_peer_notif ||
+ (bond->send_peer_notif %
+ max(1, bond->params.peer_notif_delay) != 0) ||
!netif_carrier_ok(bond->dev) ||
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
return false;
@@ -878,15 +880,18 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
if (netif_running(bond->dev)) {
bond->send_peer_notif =
- bond->params.num_peer_notif;
+ bond->params.num_peer_notif *
+ max(1, bond->params.peer_notif_delay);
should_notify_peers =
bond_should_notify_peers(bond);
}
call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev);
- if (should_notify_peers)
+ if (should_notify_peers) {
+ bond->send_peer_notif--;
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
bond->dev);
+ }
}
}
@@ -2290,6 +2295,7 @@ static void bond_mii_monitor(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
mii_work.work);
bool should_notify_peers = false;
+ bool commit;
unsigned long delay;
struct slave *slave;
struct list_head *iter;
@@ -2302,10 +2308,18 @@ static void bond_mii_monitor(struct work_struct *work)
rcu_read_lock();
should_notify_peers = bond_should_notify_peers(bond);
-
- if (bond_miimon_inspect(bond)) {
+ commit = !!bond_miimon_inspect(bond);
+ if (bond->send_peer_notif) {
+ rcu_read_unlock();
+ if (rtnl_trylock()) {
+ bond->send_peer_notif--;
+ rtnl_unlock();
+ }
+ } else {
rcu_read_unlock();
+ }
+ if (commit) {
/* Race avoidance with bond_close cancel of workqueue */
if (!rtnl_trylock()) {
delay = 1;
@@ -2319,9 +2333,7 @@ static void bond_mii_monitor(struct work_struct *work)
bond_miimon_commit(bond);
rtnl_unlock(); /* might sleep, hold no other locks */
- } else
- rcu_read_unlock();
-
+ }
re_arm:
if (bond->params.miimon)
queue_delayed_work(bond->wq, &bond->mii_work, delay);
@@ -3093,10 +3105,6 @@ static int bond_master_netdev_event(unsigned long event,
case NETDEV_REGISTER:
bond_create_proc_entry(event_bond);
break;
- case NETDEV_NOTIFY_PEERS:
- if (event_bond->send_peer_notif)
- event_bond->send_peer_notif--;
- break;
default:
break;
}
@@ -4743,6 +4751,7 @@ static int bond_check_params(struct bond_params *params)
params->arp_all_targets = arp_all_targets_value;
params->updelay = updelay;
params->downdelay = downdelay;
+ params->peer_notif_delay = 0;
params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast;
params->primary[0] = 0;
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index fbcd8a7..ae8e4e4 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -112,6 +112,7 @@ static int bond_fill_slave_info(struct sk_buff *skb,
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
.len = ETH_ALEN },
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
+ [IFLA_BOND_PEER_NOTIF_DELAY] = { .type = NLA_U32 },
};
static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
@@ -219,6 +220,14 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
if (err)
return err;
}
+ if (data[IFLA_BOND_PEER_NOTIF_DELAY]) {
+ int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]);
+
+ bond_opt_initval(&newval, delay);
+ err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval);
+ if (err)
+ return err;
+ }
if (data[IFLA_BOND_USE_CARRIER]) {
int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
@@ -497,6 +506,7 @@ static size_t bond_get_size(const struct net_device *bond_dev)
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_USER_PORT_KEY */
nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_ACTOR_SYSTEM */
nla_total_size(sizeof(u8)) + /* IFLA_BOND_TLB_DYNAMIC_LB */
+ nla_total_size(sizeof(u32)) + /* IFLA_BOND_PEER_NOTIF_DELAY */
0;
}
@@ -539,6 +549,10 @@ static int bond_fill_info(struct sk_buff *skb,
bond->params.downdelay * bond->params.miimon))
goto nla_put_failure;
+ if (nla_put_u32(skb, IFLA_BOND_PEER_NOTIF_DELAY,
+ bond->params.peer_notif_delay * bond->params.miimon))
+ goto nla_put_failure;
+
if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier))
goto nla_put_failure;
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 80867bd..ceae69c 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -28,6 +28,8 @@ static int bond_option_updelay_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_downdelay_set(struct bonding *bond,
const struct bond_opt_value *newval);
+static int bond_option_peer_notif_delay_set(struct bonding *bond,
+ const struct bond_opt_value *newval);
static int bond_option_use_carrier_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_arp_interval_set(struct bonding *bond,
@@ -78,7 +80,10 @@ static int bond_option_ad_actor_system_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_ad_user_port_key_set(struct bonding *bond,
const struct bond_opt_value *newval);
-
+static int _bond_option_delay_set(struct bonding *bond,
+ const struct bond_opt_value *newval,
+ const char *name,
+ int *target);
static const struct bond_opt_value bond_mode_tbl[] = {
{ "balance-rr", BOND_MODE_ROUNDROBIN, BOND_VALFLAG_DEFAULT},
@@ -428,6 +433,13 @@ static int bond_option_ad_user_port_key_set(struct bonding *bond,
.desc = "Number of peer notifications to send on failover event",
.values = bond_num_peer_notif_tbl,
.set = bond_option_num_peer_notif_set
+ },
+ [BOND_OPT_PEER_NOTIF_DELAY] = {
+ .id = BOND_OPT_PEER_NOTIF_DELAY,
+ .name = "peer_notif_delay",
+ .desc = "Delay between each peer notification on failover event, in milliseconds",
+ .values = bond_intmax_tbl,
+ .set = bond_option_peer_notif_delay_set
}
};
@@ -850,6 +862,9 @@ static int bond_option_miimon_set(struct bonding *bond,
if (bond->params.downdelay)
netdev_dbg(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
bond->params.downdelay * bond->params.miimon);
+ if (bond->params.peer_notif_delay)
+ netdev_dbg(bond->dev, "Note: Updating peer_notif_delay (to %d) since it is a multiple of the miimon value\n",
+ bond->params.peer_notif_delay * bond->params.miimon);
if (newval->value && bond->params.arp_interval) {
netdev_dbg(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n");
bond->params.arp_interval = 0;
@@ -873,52 +888,58 @@ static int bond_option_miimon_set(struct bonding *bond,
return 0;
}
-/* Set up and down delays. These must be multiples of the
- * MII monitoring value, and are stored internally as the multiplier.
- * Thus, we must translate to MS for the real world.
+/* Set up, down and peer notification delays. These must be multiples
+ * of the MII monitoring value, and are stored internally as the
+ * multiplier.Thus, we must translate to MS for the real world.
*/
-static int bond_option_updelay_set(struct bonding *bond,
- const struct bond_opt_value *newval)
+static int _bond_option_delay_set(struct bonding *bond,
+ const struct bond_opt_value *newval,
+ const char *name,
+ int *target)
{
int value = newval->value;
if (!bond->params.miimon) {
- netdev_err(bond->dev, "Unable to set up delay as MII monitoring is disabled\n");
+ netdev_err(bond->dev, "Unable to set %s as MII monitoring is disabled\n",
+ name);
return -EPERM;
}
if ((value % bond->params.miimon) != 0) {
- netdev_warn(bond->dev, "up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
+ netdev_warn(bond->dev,
+ "%s (%d) is not a multiple of miimon (%d), value rounded to %d ms\n",
+ name,
value, bond->params.miimon,
(value / bond->params.miimon) *
bond->params.miimon);
}
- bond->params.updelay = value / bond->params.miimon;
- netdev_dbg(bond->dev, "Setting up delay to %d\n",
- bond->params.updelay * bond->params.miimon);
+ *target = value / bond->params.miimon;
+ netdev_dbg(bond->dev, "Setting %s to %d\n",
+ name,
+ *target * bond->params.miimon);
return 0;
}
+static int bond_option_updelay_set(struct bonding *bond,
+ const struct bond_opt_value *newval)
+{
+ return _bond_option_delay_set(bond, newval, "up delay",
+ &bond->params.updelay);
+}
+
static int bond_option_downdelay_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- int value = newval->value;
-
- if (!bond->params.miimon) {
- netdev_err(bond->dev, "Unable to set down delay as MII monitoring is disabled\n");
- return -EPERM;
- }
- if ((value % bond->params.miimon) != 0) {
- netdev_warn(bond->dev, "down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
- value, bond->params.miimon,
- (value / bond->params.miimon) *
- bond->params.miimon);
- }
- bond->params.downdelay = value / bond->params.miimon;
- netdev_dbg(bond->dev, "Setting down delay to %d\n",
- bond->params.downdelay * bond->params.miimon);
+ return _bond_option_delay_set(bond, newval, "down delay",
+ &bond->params.downdelay);
+}
- return 0;
+static int bond_option_peer_notif_delay_set(struct bonding *bond,
+ const struct bond_opt_value *newval)
+{
+ return _bond_option_delay_set(bond, newval,
+ "peer notification delay",
+ &bond->params.peer_notif_delay);
}
static int bond_option_use_carrier_set(struct bonding *bond,
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 9f7d83e..850dde4 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -104,7 +104,8 @@ static void bond_info_show_master(struct seq_file *seq)
bond->params.updelay * bond->params.miimon);
seq_printf(seq, "Down Delay (ms): %d\n",
bond->params.downdelay * bond->params.miimon);
-
+ seq_printf(seq, "Peer Notification Delay (ms): %d\n",
+ bond->params.peer_notif_delay * bond->params.miimon);
/* ARP information */
if (bond->params.arp_interval > 0) {
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 3584725..0ecafe1 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -343,6 +343,18 @@ static ssize_t bonding_show_updelay(struct device *d,
static DEVICE_ATTR(updelay, 0644,
bonding_show_updelay, bonding_sysfs_store_option);
+static ssize_t bonding_show_peer_notif_delay(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n",
+ bond->params.peer_notif_delay * bond->params.miimon);
+}
+static DEVICE_ATTR(peer_notif_delay, 0644,
+ bonding_show_peer_notif_delay, bonding_sysfs_store_option);
+
/* Show the LACP interval. */
static ssize_t bonding_show_lacp(struct device *d,
struct device_attribute *attr,
@@ -734,6 +746,7 @@ static DEVICE_ATTR(ad_user_port_key, 0644,
&dev_attr_arp_ip_target.attr,
&dev_attr_downdelay.attr,
&dev_attr_updelay.attr,
+ &dev_attr_peer_notif_delay.attr,
&dev_attr_lacp_rate.attr,
&dev_attr_ad_select.attr,
&dev_attr_xmit_hash_policy.attr,
diff --git a/include/net/bond_options.h b/include/net/bond_options.h
index d79d28f..6889a04 100644
--- a/include/net/bond_options.h
+++ b/include/net/bond_options.h
@@ -67,6 +67,7 @@ enum {
BOND_OPT_AD_ACTOR_SYSTEM,
BOND_OPT_AD_USER_PORT_KEY,
BOND_OPT_NUM_PEER_NOTIF_ALIAS,
+ BOND_OPT_PEER_NOTIF_DELAY,
BOND_OPT_LAST
};
diff --git a/include/net/bonding.h b/include/net/bonding.h
index 81166488..c241010 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -114,6 +114,7 @@ struct bond_params {
int fail_over_mac;
int updelay;
int downdelay;
+ int peer_notif_delay;
int lacp_fast;
unsigned int min_links;
int ad_select;
@@ -205,7 +206,7 @@ struct bonding {
*/
spinlock_t mode_lock;
spinlock_t stats_lock;
- u8 send_peer_notif;
+ u64 send_peer_notif;
u8 igmp_retrans;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 9d8eac5..f9a0359 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -615,6 +615,7 @@ enum {
IFLA_BOND_AD_USER_PORT_KEY,
IFLA_BOND_AD_ACTOR_SYSTEM,
IFLA_BOND_TLB_DYNAMIC_LB,
+ IFLA_BOND_PEER_NOTIF_DELAY,
__IFLA_BOND_MAX,
};
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 43391e2..f57af58 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -614,6 +614,7 @@ enum {
IFLA_BOND_AD_USER_PORT_KEY,
IFLA_BOND_AD_ACTOR_SYSTEM,
IFLA_BOND_TLB_DYNAMIC_LB,
+ IFLA_BOND_PEER_NOTIF_DELAY,
__IFLA_BOND_MAX,
};
--
1.8.3.1
1
0
From: Tang Yizhou <tangyizhou(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
Provide a free area cache for the share pool VA allocator, based on the
algorithm used by linux mainline commit 89699605fe7c.
This reduces the number of rbtree operations and linear traversals over
the share pool extents in order to find a free area, by starting off at
the last point that a free area was found.
The free area cache is reset if areas are freed behind it, or if we are
searching for an another area (such as DVPP 16G area) than last time.
So allocation patterns are not changed.
After this patch, the search will start from where it left off, giving
closer to an amortized O(1).
Test environment: Huawei 1951 DC (8 CPU cores) with 21G memory, no load.
Test method: A single thread process first call sp_alloc() to allocate a
specified number of 2M hugepages, then we calculate the allocation time
when sp_alloc() another 2M hugepage. The results are in microsecond.
test 1, first sp_alloc() 256 2M-hugepage, total 512M
test 2, first sp_alloc() 512 2M-hugepage, total 1G
test 3, first sp_alloc() 1024 2M-hugepage, total 2G
test 4, first sp_alloc() 1536 2M-hugepage, total 3G
test 5, first sp_alloc() 2048 2M-hugepage, total 4G
test 6, first sp_alloc() 4096 2M-hugepage, total 8G
test 7, first sp_alloc() 6072 2M-hugepage, total 12G
test 8, first sp_alloc() 8192 2M-hugepage, total 16G
test1 test2 test3 test4
231 238 240 252 279 253 315 268
242 238 247 253 282 255 326 265
233 234 250 243 272 251 314 258
239 224 245 246 273 261 324 262
234 233 252 257 277 262 326 265
225 231 243 243 279 249 325 264
236 261 246 248 265 262 323 266
233 238 247 246 281 259 331 265
239 222 243 241 270 248 325 263
241 231 239 241 335 246 321 268
avg: 235.3 235 245.2 247 281.3 254.6 323 264.4
res: - - 9.49% 18.14%
test5 test6 test7 test8
371 280 720 458 1001 629 1547 909
369 283 691 465 1005 718 1533 903
374 279 954 470 1003 680 1371 908
363 279 697 457 1004 923 1375 930
369 286 711 464 1016 683 1395 1083
382 280 967 491 1029 695 1413 1096
378 284 688 823 1008 689 1419 905
376 360 921 469 1285 696 1554 1085
374 287 896 485 1030 682 1381 902
380 276 706 545 1286 717 1606 1097
avg: 373.6 289.4 791.5 512.7 1066.7 717.5 1459.4 981.8
res: 22.54% 35.52% 32.74% 32.73%
Suggested-by: Zefan Li <lizefan(a)huawei.com>
Signed-off-by: Tang Yizhou <tangyizhou(a)huawei.com>
Reviewed-by: Ding Tianhong <dingtianhong(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/share_pool.c | 104 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 75 insertions(+), 29 deletions(-)
diff --git a/mm/share_pool.c b/mm/share_pool.c
index 24c5dd680451..b9d30d36b7c2 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -730,6 +730,11 @@ static void __insert_sp_area(struct sp_area *spa)
rb_insert_color(&spa->rb_node, &sp_area_root);
}
+/* The sp_area cache globals are protected by sp_area_lock */
+static struct rb_node *free_sp_area_cache;
+static unsigned long cached_hole_size;
+static unsigned long cached_vstart; /* affected by SP_DVPP and sp_config_dvpp_range() */
+
/*
* Allocate a region of VA from the share pool.
* @size - the size of VA to allocate
@@ -741,7 +746,7 @@ static void __insert_sp_area(struct sp_area *spa)
static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
struct sp_group *spg, enum spa_type type)
{
- struct sp_area *spa, *err;
+ struct sp_area *spa, *first, *err;
struct rb_node *n;
unsigned long vstart = MMAP_SHARE_POOL_START;
unsigned long vend = MMAP_SHARE_POOL_16G_START;
@@ -763,8 +768,6 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
}
}
- addr = vstart;
-
spa = kmalloc(sizeof(struct sp_area), GFP_KERNEL);
if (unlikely(!spa)) {
if (printk_ratelimit())
@@ -774,45 +777,75 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
spin_lock(&sp_area_lock);
- n = sp_area_root.rb_node;
- if (n) {
- struct sp_area *first = NULL;
+ /*
+ * Invalidate cache if we have more permissive parameters.
+ * cached_hole_size notes the largest hole noticed _below_
+ * the sp_area cached in free_sp_area_cache: if size fits
+ * into that hole, we want to scan from vstart to reuse
+ * the hole instead of allocating above free_sp_area_cache.
+ * Note that sp_free_area may update free_sp_area_cache
+ * without updating cached_hole_size.
+ */
+ if (!free_sp_area_cache || size_align < cached_hole_size ||
+ vstart != cached_vstart) {
+ cached_hole_size = 0;
+ free_sp_area_cache = NULL;
+ }
+
+ /* record if we encounter less permissive parameters */
+ cached_vstart = vstart;
+
+ /* find starting point for our search */
+ if (free_sp_area_cache) {
+ first = rb_entry(free_sp_area_cache, struct sp_area, rb_node);
+ addr = first->va_end;
+ if (addr + size_align < addr) {
+ err = ERR_PTR(-EOVERFLOW);
+ goto error;
+ }
+ } else {
+ addr = vstart;
+ if (addr + size_align < addr) {
+ err = ERR_PTR(-EOVERFLOW);
+ goto error;
+ }
+
+ n = sp_area_root.rb_node;
+ first = NULL;
- do {
+ while (n) {
struct sp_area *tmp;
tmp = rb_entry(n, struct sp_area, rb_node);
if (tmp->va_end >= addr) {
- if (!first && tmp->va_start < addr + size_align)
- first = tmp;
- n = n->rb_left;
- } else {
first = tmp;
+ if (tmp->va_start <= addr)
+ break;
+ n = n->rb_left;
+ } else
n = n->rb_right;
- }
- } while (n);
+ }
if (!first)
goto found;
+ }
- if (first->va_end < addr) {
- n = rb_next(&first->rb_node);
- if (n)
- first = rb_entry(n, struct sp_area, rb_node);
- else
- goto found;
+ /* from the starting point, traverse areas until a suitable hole is found */
+ while (addr + size_align > first->va_start && addr + size_align <= vend) {
+ if (addr + cached_hole_size < first->va_start)
+ cached_hole_size = first->va_start - addr;
+ addr = first->va_end;
+ if (addr + size_align < addr) {
+ err = ERR_PTR(-EOVERFLOW);
+ goto error;
}
- while (addr + size_align >= first->va_start &&
- addr + size_align <= vend) {
- addr = first->va_end;
-
- n = rb_next(&first->rb_node);
- if (n)
- first = rb_entry(n, struct sp_area, rb_node);
- else
- goto found;
- }
+ n = rb_next(&first->rb_node);
+ if (n)
+ first = rb_entry(n, struct sp_area, rb_node);
+ else
+ goto found;
}
+
found:
if (addr + size_align > vend) {
err = ERR_PTR(-EOVERFLOW);
@@ -833,6 +866,7 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
}
__insert_sp_area(spa);
+ free_sp_area_cache = &spa->rb_node;
if (spa->spg) {
atomic_inc(&spg->spa_num);
atomic64_add(size, &spg->size);
@@ -889,6 +923,18 @@ static void sp_free_area(struct sp_area *spa)
{
lockdep_assert_held(&sp_area_lock);
+ if (free_sp_area_cache) {
+ struct sp_area *cache;
+ cache = rb_entry(free_sp_area_cache, struct sp_area, rb_node);
+ if (spa->va_start <= cache->va_start) {
+ free_sp_area_cache = rb_prev(&spa->rb_node);
+ /*
+ * We don't try to update cached_hole_size,
+ * but it won't go very wrong.
+ */
+ }
+ }
+
spa_dec_usage(spa->type, spa->real_size); /* won't fail */
if (spa->spg) {
atomic_dec(&spa->spg->spa_num);
--
2.25.1
1
5
From: Di Wang <wangdi44(a)huawei.com>
driver inclusion
category: bugfix
bugzilla: NA
Link: https://gitee.com/openeuler/kernel/issues/I1WGZE
--------------------------------
It will cost a lot of time when synchronize_rcu() is called for every
namspace in nvme_stop_queues().
Reviewed-by: Chao Leng <lengchao(a)huawei.com>
Reviewed-by: Jike Cheng <chengjike.cheng(a)huawei.com>
Signed-off-by: Di Wang <wangdi44(a)huawei.com>
Signed-off-by: Lijie <lijie34(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
Reviewed-by: Hou Tao <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
block/blk-mq.c | 18 ++++++++++++++++++
drivers/nvme/host/core.c | 6 +++++-
include/linux/blk-mq.h | 1 +
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 7096f23b18da..41e92dbff821 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -242,6 +242,24 @@ void blk_mq_quiesce_queue(struct request_queue *q)
}
EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
+bool blk_mq_quiesce_queue_without_rcu(struct request_queue *q)
+{
+ struct blk_mq_hw_ctx *hctx;
+ unsigned int i;
+ bool rcu = false;
+
+ blk_mq_quiesce_queue_nowait(q);
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ if (hctx->flags & BLK_MQ_F_BLOCKING)
+ synchronize_srcu(hctx->srcu);
+ else
+ rcu = true;
+ }
+ return rcu;
+}
+EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_without_rcu);
+
/*
* blk_mq_unquiesce_queue() - counterpart of blk_mq_quiesce_queue()
* @q: request queue.
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 8443c6c5c5af..c9faa824de26 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3904,11 +3904,15 @@ EXPORT_SYMBOL_GPL(nvme_start_freeze);
void nvme_stop_queues(struct nvme_ctrl *ctrl)
{
struct nvme_ns *ns;
+ bool rcu = false;
down_read(&ctrl->namespaces_rwsem);
list_for_each_entry(ns, &ctrl->namespaces, list)
- blk_mq_quiesce_queue(ns->queue);
+ rcu = (blk_mq_quiesce_queue_without_rcu(ns->queue) || rcu);
up_read(&ctrl->namespaces_rwsem);
+
+ if (rcu)
+ synchronize_rcu();
}
EXPORT_SYMBOL_GPL(nvme_stop_queues);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index d26edab21d5c..730de600075b 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -309,6 +309,7 @@ void blk_mq_start_hw_queues(struct request_queue *q);
void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async);
void blk_mq_quiesce_queue(struct request_queue *q);
+bool blk_mq_quiesce_queue_without_rcu(struct request_queue *q);
void blk_mq_unquiesce_queue(struct request_queue *q);
void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
bool blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
--
2.25.1
1
1
Hi 亚芬,
On 2020/12/1 16:47, 方亚芬 wrote:
> 内核组的老师们,大家好。我是 openEuler 社区树莓派 SIG 组的 maintainer 方亚芬。
>
>
> 针对即将发布的 openEuler 20.03 LTS SP1,有个问题想咨询一下。
>
> 当前 openEuler 4.19 内核源码最新版本为 4.19.90-2011.6.0(https://gitee.com/openeuler/kernel/tree/4.19.90-2011.6.0/)… src-openeuler/kernel(https://gitee.com/src-openeuler/kernel) 下三个分支更新版本不同,分别为:
> 1. openEuler 20.03 LTS Next:4.19.90-2010.2.0
> 2. openEuler 20.03 LTS SP1:4.19.90-2011.4.0
> 3. openEuler 20.03 LTS:4.19.90-2011.6.0
>
>
> 针对该情况有以下两个问题:
> 1. 之前树莓派镜像的内核版本一直根据 src-openeuler/kernel 下内核版本做更新,即将发布的 openEuler 20.03 LTS SP1
> 树莓派镜像采用内核版本要与 src-openeuler/kernel 的 openEuler 20.03 LTS SP1 分支内核版本一致?还是需要采用 openEuler 4.19 内核源码的最新版本(https://gitee.com/openeuler/kernel/tree/openEuler-1.0-LTS/,当前为 4.19.90-2011.6.0)?
20.03 LTS SP1 和 20.03 LTS 的kernel同源,使用相同的内核分支,4.19.90-2011.4.0 和 4.19.90-2011.6.0 只是合入节奏的问题,实际上是同一个分支。
对应的源码分支都是 openEuler-1.0-LTS.
>
> 2. openEuler 20.03 LTS SP1 正式发布前,内核会一直不定期更新,还是会有个具体的截止时间停止更新呢?
>
SP1 包括之前的 20.03 LTS 都会陆续有少量的 cve 或 bugfix 补丁,SP1 正式发布之后,也会有陆续的更新,
会持续到 SP1、SP0 生命周期结束。
我理解你的诉求,你关心树莓派的内核 rebase 到openEuler具体哪个版本。我觉得这个影响应该不大,近期到
SP1 release,合入的补丁应该会很少。
这个 SP1 的 release 计划,
https://gitee.com/openeuler/release-management/blob/master/openEuler-20.03-…
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> 祝工作顺利,生活愉快。
>
> ------------------------------------------
> 方亚芬
> 中国科学院软件研究所 智能软件研究中心
> 邮箱:yafen(a)iscas.ac.cn <mailto:jiran@iscas.ac.cn>
> 地址:北京市海淀区中关村南四街4号5楼
>
> _______________________________________________
> Release mailing list -- release(a)openeuler.org
> To unsubscribe send an email to release-leave(a)openeuler.org
>
2
1
亲爱的 openEuler 社区开发者:
openEuler Summit 是由 openEuler 社区举办的开发者交流会,首届线下 openEuler Summit 2020 将于 12 月 24-25 日在北京・望京凯悦酒店举办。openEuler 是一个面向未来的开源操作系统,依托于最具活力的 openEuler 社区,它的未来将不止于操作系统!
openEuler Summit 2020 将聚焦于软硬件协同、云边端协同的技术趋势,万物互联的多算力场景,挖掘技术创新与社区生态的价值。开发者、用户、社区贡献者、软件爱好者在 openEuler Summit 上汇聚成海,连接行业上下游,让全产业链共享操作系统创新价值。
目前各大 Session 议题已经评审完毕,今日将会上线部分议程,大会报名通道开启,TC、Maintainer、SIG 工作组会议也在有条不紊地推进中。我们也将持续向大家同步会议进程,以便于社区成员了解 openEuler Summit 最新进展。
openEuler Summit 社区内开发者报名专属通道:https://etherpad.openeuler.org/p/openEuler-Summit-2020
在 openEuler 一周年之际,大会准备了一个 100个社区开发者为openEuler 代言的视频,诚挚地邀请您按照下方的要求拍摄一段视频,将 openEuler 操作系统推荐给更多的人。
拍摄需求:
自拍形式,对着镜头回答以下问题:
1. 我想要的操作系统是****的,
2. 我在**时候参与/认识/加入/知道的openEuler(社区)
3. 我在openEuler贡献了****
4. 我是***,我为openEuler代言
使用场景:
您拍摄的视频素材将用于 openEuler Summit 2020 前期的会议宣传和开场视频中。
拍摄指导:
1. 背景任您喜欢
2. 人物面对镜头,取半身构图,横向拍摄16:9 的画面比例
3. 最好选择白炽灯,白色光源
4. 尽量由另一个人辅助,用手机后置摄像头拍摄,不要用前置,拍摄前擦拭摄像头
5. 读口播时,声音越大越好
6. 尽量保证每一句话都是完整通顺的,中间重来的部分可以忽略
7. 视频输出,用电脑将手机视频导出,打压缩包传输即可(不要用微信上传,会压缩画质)
8. 拍摄完毕后请将视频上传到百度网盘,将分享链接期限设置为永久,然后发给 public(a)openeuler.io
9. 样片在附件,请您参考
1
0
[PATCH 1/3] Revert "refcount_t: Add ACQUIRE ordering on success for dec(sub)_and_test() variants"
by Yang Yingliang 28 Nov '20
by Yang Yingliang 28 Nov '20
28 Nov '20
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
----------------------------------------
This reverts commit 99294378e022ec2785f88247a7373767fd090e3a.
288e4521f0f6 ("x86/asm: 'Simplify' GEN_*_RMWcc() macros") need
be apply before this commit to avoid compile error.
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
Documentation/core-api/refcount-vs-atomic.rst | 24 +++----------------
arch/x86/include/asm/refcount.h | 18 ++------------
lib/refcount.c | 18 ++++----------
3 files changed, 10 insertions(+), 50 deletions(-)
diff --git a/Documentation/core-api/refcount-vs-atomic.rst b/Documentation/core-api/refcount-vs-atomic.rst
index 976e85adffe8..322851bada16 100644
--- a/Documentation/core-api/refcount-vs-atomic.rst
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -54,13 +54,6 @@ must propagate to all other CPUs before the release operation
(A-cumulative property). This is implemented using
:c:func:`smp_store_release`.
-An ACQUIRE memory ordering guarantees that all post loads and
-stores (all po-later instructions) on the same CPU are
-completed after the acquire operation. It also guarantees that all
-po-later stores on the same CPU must propagate to all other CPUs
-after the acquire operation executes. This is implemented using
-:c:func:`smp_acquire__after_ctrl_dep`.
-
A control dependency (on success) for refcounters guarantees that
if a reference for an object was successfully obtained (reference
counter increment or addition happened, function returned true),
@@ -126,24 +119,13 @@ Memory ordering guarantees changes:
result of obtaining pointer to the object!
-case 5) - generic dec/sub decrement-based RMW ops that return a value
----------------------------------------------------------------------
+case 5) - decrement-based RMW ops that return a value
+-----------------------------------------------------
Function changes:
* :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test`
* :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test`
-
-Memory ordering guarantees changes:
-
- * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
-
-
-case 6) other decrement-based RMW ops that return a value
----------------------------------------------------------
-
-Function changes:
-
* no atomic counterpart --> :c:func:`refcount_dec_if_one`
* ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)``
@@ -154,7 +136,7 @@ Memory ordering guarantees changes:
.. note:: :c:func:`atomic_add_unless` only provides full order on success.
-case 7) - lock-based RMW
+case 6) - lock-based RMW
------------------------
Function changes:
diff --git a/arch/x86/include/asm/refcount.h b/arch/x86/include/asm/refcount.h
index 88061df7add6..19b90521954c 100644
--- a/arch/x86/include/asm/refcount.h
+++ b/arch/x86/include/asm/refcount.h
@@ -67,28 +67,14 @@ static __always_inline void refcount_dec(refcount_t *r)
static __always_inline __must_check
bool refcount_sub_and_test(unsigned int i, refcount_t *r)
{
- bool ret = GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", REFCOUNT_CHECK_LT_ZERO,
+ GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", REFCOUNT_CHECK_LT_ZERO,
r->refs.counter, "er", i, "%0", e, "cx");
-
- if (ret) {
- smp_acquire__after_ctrl_dep();
- return true;
- }
-
- return false;
}
static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
{
- bool ret = GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", REFCOUNT_CHECK_LT_ZERO,
+ GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", REFCOUNT_CHECK_LT_ZERO,
r->refs.counter, "%0", e, "cx");
-
- if (ret) {
- smp_acquire__after_ctrl_dep();
- return true;
- }
-
- return false;
}
static __always_inline __must_check
diff --git a/lib/refcount.c b/lib/refcount.c
index 6e904af0fb3e..ebcf8cd49e05 100644
--- a/lib/refcount.c
+++ b/lib/refcount.c
@@ -33,9 +33,6 @@
* Note that the allocator is responsible for ordering things between free()
* and alloc().
*
- * The decrements dec_and_test() and sub_and_test() also provide acquire
- * ordering on success.
- *
*/
#include <linux/mutex.h>
@@ -167,8 +164,8 @@ EXPORT_SYMBOL(refcount_inc_checked);
* at UINT_MAX.
*
* Provides release memory ordering, such that prior loads and stores are done
- * before, and provides an acquire ordering on success such that free()
- * must come after.
+ * before, and provides a control dependency such that free() must come after.
+ * See the comment on top.
*
* Use of this function is not recommended for the normal reference counting
* use case in which references are taken and released one at a time. In these
@@ -193,12 +190,7 @@ bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r)
} while (!atomic_try_cmpxchg_release(&r->refs, &val, new));
- if (!new) {
- smp_acquire__after_ctrl_dep();
- return true;
- }
- return false;
-
+ return !new;
}
EXPORT_SYMBOL(refcount_sub_and_test_checked);
@@ -210,8 +202,8 @@ EXPORT_SYMBOL(refcount_sub_and_test_checked);
* decrement when saturated at UINT_MAX.
*
* Provides release memory ordering, such that prior loads and stores are done
- * before, and provides an acquire ordering on success such that free()
- * must come after.
+ * before, and provides a control dependency such that free() must come after.
+ * See the comment on top.
*
* Return: true if the resulting refcount is 0, false otherwise
*/
--
2.25.1
1
2
[PATCH 01/11] mm: move nr_deactivate accounting to shrink_active_list()
by Yang Yingliang 28 Nov '20
by Yang Yingliang 28 Nov '20
28 Nov '20
From: Kirill Tkhai <ktkhai(a)virtuozzo.com>
mainline inclusion
from mainline-v5.2-rc1
commit 9851ac13592df77958ae7bac6ba39e71420c38ec
category: bugfix
bugzilla: 36232
CVE: NA
-------------------------------------------------
We know which LRU is not active.
[chris(a)chrisdown.name: fix build on !CONFIG_MEMCG]
Link: http://lkml.kernel.org/r/20190322150513.GA22021@chrisdown.name
Link: http://lkml.kernel.org/r/155290128498.31489.18250485448913338607.stgit@loca…
Signed-off-by: Kirill Tkhai <ktkhai(a)virtuozzo.com>
Signed-off-by: Chris Down <chris(a)chrisdown.name>
Reviewed-by: Daniel Jordan <daniel.m.jordan(a)oracle.com>
Cc: Michal Hocko <mhocko(a)kernel.org>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
Signed-off-by: Liu Shixin <liushixin2(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/memcontrol.h | 6 ++++++
mm/vmscan.c | 10 ++++------
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index f6f51b14a332..029b4848ab6f 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -1109,6 +1109,12 @@ static inline void count_memcg_events(struct mem_cgroup *memcg,
{
}
+static inline void __count_memcg_events(struct mem_cgroup *memcg,
+ enum vm_event_item idx,
+ unsigned long count)
+{
+}
+
static inline void count_memcg_page_event(struct page *page,
int idx)
{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 38fcda38bf7b..92f2489efda8 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2077,12 +2077,6 @@ static unsigned move_active_pages_to_lru(struct lruvec *lruvec,
}
}
- if (!is_active_lru(lru)) {
- __count_vm_events(PGDEACTIVATE, nr_moved);
- count_memcg_events(lruvec_memcg(lruvec), PGDEACTIVATE,
- nr_moved);
- }
-
return nr_moved;
}
@@ -2178,6 +2172,10 @@ static void shrink_active_list(unsigned long nr_to_scan,
nr_activate = move_active_pages_to_lru(lruvec, &l_active, &l_hold, lru);
nr_deactivate = move_active_pages_to_lru(lruvec, &l_inactive, &l_hold, lru - LRU_ACTIVE);
+
+ __count_vm_events(PGDEACTIVATE, nr_deactivate);
+ __count_memcg_events(lruvec_memcg(lruvec), PGDEACTIVATE, nr_deactivate);
+
__mod_node_page_state(pgdat, NR_ISOLATED_ANON + file, -nr_taken);
spin_unlock_irq(&pgdat->lru_lock);
--
2.25.1
1
10
From: YueHaibing <yuehaibing(a)huawei.com>
mainline inclusion
from mainline-v4.20-rc1
commit efbaec89c642cd1d4977fc6df9923697e1598d4e
category: other
bugzilla: 43460
CVE: NA
---------------------------------------
Remove duplicated include.
Signed-off-by: YueHaibing <yuehaibing(a)huawei.com>
Signed-off-by: Daniel Borkmann <daniel(a)iogearbox.net>
Signed-off-by: liuxin <liuxin264(a)huawei.com>
Reviewed-by: Cheng Jian <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
kernel/bpf/syscall.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index cb473159a55c..3e9ff9897c7c 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -30,7 +30,6 @@
#include <linux/cred.h>
#include <linux/timekeeping.h>
#include <linux/ctype.h>
-#include <linux/btf.h>
#include <linux/nospec.h>
#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \
--
2.25.1
1
12
Aaron Lewis (1):
selftests: kvm: Fix the segment descriptor layout to match the actual
layout
Alejandro Concepcion Rodriguez (1):
can: dev: can_restart(): post buffer from the right context
Anant Thazhemadam (2):
can: af_can: prevent potential access of uninitialized member in
can_rcv()
can: af_can: prevent potential access of uninitialized member in
canfd_rcv()
Arvind Sankar (1):
efi/x86: Free efi_pgd with free_pages()
Aya Levin (1):
net/mlx4_core: Fix init_hca fields offset
Brian O'Keefe (1):
staging: rtl8723bs: Add 024c:0627 to the list of SDIO device-ids
Can Guo (1):
scsi: ufs: Fix unbalanced scsi_block_reqs_cnt caused by ufshcd_hold()
Chen Yu (1):
x86/microcode/intel: Check patch signature before saving microcode for
early loading
Chen-Yu Tsai (4):
Revert "arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active
high"
ARM: dts: sun8i: h3: orangepi-plus2e: Enable RGMII RX/TX delay on
Ethernet PHY
ARM: dts: sun8i: a83t: Enable both RGMII RX/TX delay on Ethernet PHY
arm64: dts: allwinner: a64: bananapi-m64: Enable RGMII RX/TX delay on
PHY
Colin Ian King (1):
can: peak_usb: fix potential integer overflow on shift of a int
Dan Carpenter (2):
Input: adxl34x - clean up a data type in adxl34x_probe()
ALSA: firewire: Clean up a locking issue in copy_resp_to_buf()
Darrick J. Wong (4):
vfs: remove lockdep bogosity in __sb_start_write
xfs: fix the minrecs logic when dealing with inode root child blocks
xfs: strengthen rmap record flags checking
xfs: revert "xfs: fix rmap key and record comparison functions"
Dongli Zhang (1):
page_frag: Recover from memory pressure
Edwin Peer (1):
bnxt_en: read EEPROM A2h address using page 0
Fabio Estevam (1):
ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
Felix Fietkau (2):
mac80211: minstrel: remove deferred sampling code
mac80211: minstrel: fix tx status processing corner case
Filip Moc (1):
net: usb: qmi_wwan: Set DTR quirk for MR400
Florian Fainelli (1):
net: Have netpoll bring-up DSA management interface
Fugang Duan (1):
tty: serial: imx: keep console clocks always on
Gerald Schaefer (1):
mm/userfaultfd: do not access vma->vm_mm after calling
handle_userfault()
Greg Kroah-Hartman (1):
Linux 4.19.160
Hans de Goede (3):
ACPI: button: Add DMI quirk for Medion Akoya E2228T
iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type
enum
iio: accel: kxcjk1013: Add support for KIOX010A ACPI DSM for setting
tablet-mode
Heiner Kallweit (1):
net: bridge: add missing counters to ndo_get_stats64 callback
Ido Schimmel (1):
mlxsw: core: Use variable timeout for EMAD retries
Jan Kara (1):
ext4: fix bogus warning in ext4_update_dx_flag()
Jernej Skrabec (3):
arm64: dts: allwinner: a64: Pine64 Plus: Fix ethernet node
arm64: dts: allwinner: h5: OrangePi PC2: Fix ethernet node
ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix ethernet node
Jianqun Xu (1):
pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
Jimmy Assarsson (1):
can: kvaser_usb: kvaser_usb_hydra: Fix KCAN bittiming limits
Joakim Tjernlund (1):
ALSA: usb-audio: Add delay quirk for all Logitech USB devices
Joel Stanley (2):
net/ncsi: Fix netlink registration
net: ftgmac100: Fix crash when removing driver
Johannes Berg (1):
mac80211: free sta in sta_info_insert_finish() on errors
Leo Yan (1):
perf lock: Don't free "lock_seq_stat" if read_count isn't zero
Luo Meng (1):
fail_function: Remove a redundant mutex unlock
Marc Kleine-Budde (1):
can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to
can_put_echo_skb()
Max Filippov (1):
xtensa: disable preemption around cache alias management calls
Michał Mirosław (3):
regulator: fix memory leak with repeated set_machine_constraints()
regulator: avoid resolve_supply() infinite recursion
regulator: workaround self-referent regulators
Mickaël Salaün (2):
ptrace: Set PF_SUPERPRIV when checking capability
seccomp: Set PF_SUPERPRIV when checking capability
Necip Fazil Yildiran (1):
Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
Nenad Peric (1):
arm64: dts: allwinner: h5: OrangePi Prime: Fix ethernet node
Nishanth Menon (1):
regulator: ti-abb: Fix array out of bound read access on the first
transition
Paul Moore (2):
netlabel: fix our progress tracking in netlbl_unlabel_staticlist()
netlabel: fix an uninitialized warning in netlbl_unlabel_staticlist()
PeiSen Hou (1):
ALSA: hda/realtek: Add some Clove SSID in the ALC293(ALC1220)
Randy Dunlap (1):
MIPS: export has_transparent_hugepage() for modules
Ryan Sharpelletti (1):
tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
Sean Nyekjaer (1):
regulator: pfuze100: limit pfuze-support-disable-sw to pfuze{100,200}
Sebastian Andrzej Siewior (1):
atm: nicstar: Unmap DMA on send error
Sergey Matyukevich (1):
arm: dts: imx6qdl-udoo: fix rgmii phy-mode for ksz9031 phy
Srinivasa Rao Mandadapu (1):
ASoC: qcom: lpass-platform: Fix memory leak
Stefan Haberland (1):
s390/dasd: fix null pointer dereference for ERP requests
Subash Abhinov Kasiviswanathan (1):
net: qualcomm: rmnet: Fix incorrect receive packet handling during
cleanup
Sven Van Asbroeck (2):
lan743x: fix issue causing intermittent kernel log warnings
lan743x: prevent entire kernel HANG on open, for some platforms
Takashi Iwai (1):
ALSA: mixart: Fix mutex deadlock
Takashi Sakamoto (1):
ALSA: ctl: fix error path at adding user-defined element set
Thomas Richter (1):
s390/cpum_sf.c: fix file permission for cpum_sfb_size
Tobias Waldekranz (1):
net: dsa: mv88e6xxx: Avoid VTU corruption on 6097
Vamshi K Sthambamkadi (1):
efivarfs: fix memory leak in efivarfs_create()
Vladyslav Tarasiuk (1):
net/mlx5: Disable QoS when min_rates on all VFs are zero
Wang Hai (2):
devlink: Add missing genlmsg_cancel() in
devlink_nl_sb_port_pool_fill()
inet_diag: Fix error path to cancel the meseage in
inet_req_diag_fill()
Will Deacon (1):
arm64: psci: Avoid printing in cpu_psci_cpu_die()
Wu Bo (1):
can: m_can: m_can_handle_state_change(): fix state change
Xie He (1):
net: x25: Increase refcnt of "struct x25_neigh" in x25_rx_call_request
Xin Long (1):
sctp: change to hold/put transport for proto_unreach_timer
Xiongfeng Wang (1):
drm/sun4i: dw-hdmi: fix error return code in sun8i_dw_hdmi_bind()
Yi-Hung Wei (1):
ip_tunnels: Set tunnel option flag when tunnel metadata is present
Yicong Yang (1):
libfs: fix error cast of negative value in simple_attr_write()
Zhang Changzhong (4):
ah6: fix error return code in ah6_input()
net: b44: fix error return code in b44_init_one()
qed: fix error return code in qed_iwarp_ll2_start()
qlcnic: fix error return code in qlcnic_83xx_restart_hw()
Zhang Qilong (2):
can: ti_hecc: Fix memleak in ti_hecc_probe
MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
Makefile | 2 +-
arch/arm/boot/dts/imx50-evk.dts | 2 +-
arch/arm/boot/dts/imx6qdl-udoo.dtsi | 2 +-
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts | 2 +-
.../boot/dts/sun8i-a83t-cubietruck-plus.dts | 2 +-
.../boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5 --
.../arm/boot/dts/sun8i-h3-orangepi-plus2e.dts | 2 +-
.../boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 2 +-
.../dts/allwinner/sun50i-a64-bananapi-m64.dts | 2 +-
.../dts/allwinner/sun50i-a64-pine64-plus.dts | 2 +-
.../dts/allwinner/sun50i-h5-orangepi-pc2.dts | 2 +-
.../allwinner/sun50i-h5-orangepi-prime.dts | 2 +-
arch/arm64/kernel/psci.c | 5 +-
arch/mips/alchemy/common/clock.c | 9 ++-
arch/mips/mm/tlb-r4k.c | 1 +
arch/s390/kernel/perf_cpum_sf.c | 2 +-
arch/x86/kernel/cpu/microcode/intel.c | 63 +++----------------
arch/x86/platform/efi/efi_64.c | 24 +++----
arch/xtensa/mm/cache.c | 14 +++++
drivers/acpi/button.c | 13 +++-
drivers/atm/nicstar.c | 2 +
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 1 +
drivers/iio/accel/kxcjk-1013.c | 51 +++++++++++++--
drivers/input/misc/adxl34x.c | 2 +-
drivers/input/touchscreen/Kconfig | 1 +
drivers/net/can/dev.c | 2 +-
drivers/net/can/m_can/m_can.c | 4 +-
drivers/net/can/ti_hecc.c | 13 ++--
.../net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 2 +-
drivers/net/can/usb/mcba_usb.c | 4 +-
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 4 +-
drivers/net/dsa/mv88e6xxx/global1_vtu.c | 59 ++++++++++++++---
drivers/net/ethernet/broadcom/b44.c | 3 +-
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +-
drivers/net/ethernet/faraday/ftgmac100.c | 4 ++
drivers/net/ethernet/mellanox/mlx4/fw.c | 6 +-
drivers/net/ethernet/mellanox/mlx4/fw.h | 4 +-
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 15 ++---
drivers/net/ethernet/mellanox/mlxsw/core.c | 3 +-
drivers/net/ethernet/microchip/lan743x_main.c | 13 ++--
drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 12 +++-
.../ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 3 +-
.../ethernet/qualcomm/rmnet/rmnet_handlers.c | 5 ++
drivers/net/geneve.c | 3 +-
drivers/net/usb/qmi_wwan.c | 2 +-
drivers/pinctrl/pinctrl-rockchip.c | 2 +
drivers/regulator/core.c | 38 ++++++-----
drivers/regulator/pfuze100-regulator.c | 13 ++--
drivers/regulator/ti-abb-regulator.c | 12 +++-
drivers/s390/block/dasd.c | 6 ++
drivers/scsi/ufs/ufshcd.c | 6 +-
drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 1 +
drivers/tty/serial/imx.c | 20 +-----
fs/efivarfs/super.c | 1 +
fs/ext4/ext4.h | 3 +-
fs/libfs.c | 6 +-
fs/super.c | 33 ++--------
fs/xfs/libxfs/xfs_rmap_btree.c | 16 ++---
fs/xfs/scrub/bmap.c | 8 +--
fs/xfs/scrub/btree.c | 45 +++++++------
include/net/ip_tunnels.h | 7 ++-
kernel/fail_function.c | 5 +-
kernel/ptrace.c | 16 ++---
kernel/seccomp.c | 5 +-
mm/huge_memory.c | 9 ++-
mm/page_alloc.c | 5 ++
net/bridge/br_device.c | 1 +
net/can/af_can.c | 38 ++++++++---
net/core/devlink.c | 6 +-
net/core/netpoll.c | 22 +++++--
net/ipv4/inet_diag.c | 4 +-
net/ipv4/tcp_bbr.c | 2 +-
net/ipv6/ah6.c | 3 +-
net/mac80211/rc80211_minstrel.c | 27 ++------
net/mac80211/rc80211_minstrel.h | 1 -
net/mac80211/sta_info.c | 14 ++---
net/ncsi/ncsi-manage.c | 5 --
net/ncsi/ncsi-netlink.c | 22 +------
net/ncsi/ncsi-netlink.h | 3 -
net/netlabel/netlabel_unlabeled.c | 17 +++--
net/sctp/input.c | 4 +-
net/sctp/sm_sideeffect.c | 4 +-
net/sctp/transport.c | 2 +-
net/x25/af_x25.c | 1 +
sound/core/control.c | 2 +-
.../fireworks/fireworks_transaction.c | 4 +-
sound/pci/hda/patch_realtek.c | 50 ++++++++++++++-
sound/pci/mixart/mixart_core.c | 5 +-
sound/soc/qcom/lpass-platform.c | 5 +-
sound/usb/quirks.c | 10 +--
tools/perf/builtin-lock.c | 2 +-
tools/testing/selftests/kvm/include/x86.h | 2 +-
tools/testing/selftests/kvm/lib/x86.c | 3 +-
93 files changed, 517 insertions(+), 377 deletions(-)
--
2.25.1
1
91
[PATCH 01/14] blk-cgroup: prevent rcu_sched detected stalls warnings in blkg_destroy_all()
by Yang Yingliang 28 Nov '20
by Yang Yingliang 28 Nov '20
28 Nov '20
From: Yu Kuai <yukuai3(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 46357
CVE: NA
---------------------------
test procedures:
a. create 20000 cgroups, and echo "8:0 10000" to
blkio.throttle.write_bps_device
b. echo 1 > /sys/blocd/sda/device/delete
test result:
rcu: INFO: rcu_sched detected stalls on CPUs/tasks: [5/1143]
rcu: 0-...0: (0 ticks this GP) idle=0f2/1/0x4000000000000000 softirq=15507/15507 fq
rcu: (detected by 6, t=60012 jiffies, g=119977, q=27153)
NMI backtrace for cpu 0
CPU: 0 PID: 443 Comm: bash Not tainted 4.19.95-00061-g0bcc83b30eec #63
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-p4
RIP: 0010:blk_throtl_update_limit_valid.isra.0+0x116/0x2a0
Code: 01 00 00 e8 7c dd 74 ff 48 83 bb 78 01 00 00 00 0f 85 54 01 00 00 48 8d bb 88 01 1
RSP: 0018:ffff8881030bf9f0 EFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff8880b4f37080 RCX: ffffffff95da0afe
RDX: dffffc0000000000 RSI: ffff888100373980 RDI: ffff8880b4f37208
RBP: ffff888100deca00 R08: ffffffff9528f951 R09: 0000000000000001
R10: ffffed10159dbf56 R11: ffff8880acedfab3 R12: ffff8880b9fda498
R13: ffff8880b9fda4f4 R14: 0000000000000050 R15: ffffffff98b622c0
FS: 00007feb51c51700(0000) GS:ffff888106200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000561619547080 CR3: 0000000102bc9000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
throtl_pd_offline+0x98/0x100
blkg_destroy+0x133/0x630
? blkcg_deactivate_policy+0x2c0/0x2c0
? lock_timer_base+0x65/0x110
blkg_destroy_all+0x7f/0x100
blkcg_exit_queue+0x3f/0xa5
blk_exit_queue+0x69/0xa0
blk_cleanup_queue+0x226/0x360
__scsi_remove_device+0xb4/0x3c0
scsi_remove_device+0x38/0x60
sdev_store_delete+0x74/0x100
? dev_driver_string+0xb0/0xb0
dev_attr_store+0x41/0x70
sysfs_kf_write+0x89/0xc0
kernfs_fop_write+0x1b6/0x2e0
? sysfs_kf_bin_read+0x130/0x130
__vfs_write+0xca/0x420
? kernel_read+0xc0/0xc0
? __alloc_fd+0x16f/0x2d0
? __fd_install+0x95/0x1a0
? handle_mm_fault+0x3e0/0x560
vfs_write+0x11a/0x2f0
ksys_write+0xb9/0x1e0
? __x64_sys_read+0x60/0x60
? kasan_check_write+0x20/0x30
? filp_close+0xb5/0xf0
__x64_sys_write+0x46/0x60
do_syscall_64+0xd9/0x1f0
entry_SYSCALL_64_after_hwframe+0x44/0xa9
The usage of so many blkg is very rare, however, such problem do exist
in theory. In order to avoid such warnings, release 'q->queue_lock' for
a while when a batch of blkg were destroyed.
Signed-off-by: Yu Kuai <yukuai3(a)huawei.com>
Reviewed-by: Tao Hou <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
block/blk-cgroup.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e592167449aa..c64f0afa27dc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -364,16 +364,31 @@ static void blkg_destroy(struct blkcg_gq *blkg)
*/
static void blkg_destroy_all(struct request_queue *q)
{
+#define BLKG_DESTROY_BATCH 4096
struct blkcg_gq *blkg, *n;
+ int count;
lockdep_assert_held(q->queue_lock);
+again:
+ count = BLKG_DESTROY_BATCH;
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
struct blkcg *blkcg = blkg->blkcg;
spin_lock(&blkcg->lock);
blkg_destroy(blkg);
spin_unlock(&blkcg->lock);
+ /*
+ * If the list is too long, the loop can took a long time,
+ * thus relese the lock for a while when a batch of blkg
+ * were destroyed.
+ */
+ if (!--count) {
+ spin_unlock_irq(q->queue_lock);
+ cond_resched();
+ spin_lock_irq(q->queue_lock);
+ goto again;
+ }
}
q->root_blkg = NULL;
--
2.25.1
1
13
2
1
From: Mingwang Li <limingwang(a)huawei.com>
euleros inclusion
category: feature
bugzilla: NA
CVE: NA
This series adds initial KVM RISC-V support. Currently, we are able to boot
Linux on RV64/RV32 Guest with multiple VCPUs.
This series can be found in riscv_kvm_v15 branch at:
https//github.com/avpatel/linux.git
Link: https://gitee.com/openeuler/kernel/issues/I26X9V
Alistair Francis (1):
Revert "riscv: Use latest system call ABI"
Anup Patel (20):
RISC-V: Add fragmented config for debug options
RISC-V: Enable CPU Hotplug in defconfigs
RISC-V: Add Microchip PolarFire kconfig option
RISC-V: Initial DTS for Microchip ICICLE board
RISC-V: Enable drivers for Microchip PolarFire ICICLE board
RISC-V: Add missing jump label initialization
RISC-V: Add hypervisor extension related CSR defines
RISC-V: Add initial skeletal KVM support
RISC-V: KVM: Implement VCPU create, init and destroy functions
RISC-V: KVM: Implement VCPU interrupts and requests handling
RISC-V: KVM: Implement KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls
RISC-V: KVM: Implement VCPU world-switch
RISC-V: KVM: Handle MMIO exits for VCPU
RISC-V: KVM: Handle WFI exits for VCPU
RISC-V: KVM: Implement VMID allocator
RISC-V: KVM: Implement stage2 page table programming
RISC-V: KVM: Implement MMU notifiers
RISC-V: KVM: Document RISC-V specific parts of KVM API
RISC-V: KVM: Add MAINTAINERS entry
RISC-V: Enable KVM for RV64 and RV32
Atish Patra (4):
RISC-V: KVM: Add timer functionality
RISC-V: KVM: FP lazy save/restore
RISC-V: KVM: Implement ONE REG interface for FP registers
RISC-V: KVM: Add SBI v0.1 support
m34782 (1):
Microchip Polarfire SoC Clock Driver
Documentation/virt/kvm/api.rst | 193 +++-
MAINTAINERS | 11 +
arch/riscv/Kconfig | 2 +
arch/riscv/Kconfig.socs | 7 +
arch/riscv/Makefile | 2 +
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/microchip/Makefile | 2 +
.../boot/dts/microchip/icicle-kit-es.dts | 307 +++++
arch/riscv/configs/defconfig | 30 +-
arch/riscv/configs/extra_debug.config | 21 +
arch/riscv/configs/rv32_defconfig | 26 +-
arch/riscv/include/asm/csr.h | 89 ++
arch/riscv/include/asm/kvm_host.h | 279 +++++
arch/riscv/include/asm/kvm_types.h | 7 +
arch/riscv/include/asm/kvm_vcpu_timer.h | 44 +
arch/riscv/include/asm/pgtable-bits.h | 1 +
arch/riscv/include/uapi/asm/kvm.h | 128 +++
arch/riscv/include/uapi/asm/unistd.h | 5 +-
arch/riscv/kernel/asm-offsets.c | 156 +++
arch/riscv/kernel/setup.c | 1 +
arch/riscv/kvm/Kconfig | 36 +
arch/riscv/kvm/Makefile | 15 +
arch/riscv/kvm/main.c | 118 ++
arch/riscv/kvm/mmu.c | 860 ++++++++++++++
arch/riscv/kvm/tlb.S | 74 ++
arch/riscv/kvm/vcpu.c | 1012 +++++++++++++++++
arch/riscv/kvm/vcpu_exit.c | 701 ++++++++++++
arch/riscv/kvm/vcpu_sbi.c | 173 +++
arch/riscv/kvm/vcpu_switch.S | 400 +++++++
arch/riscv/kvm/vcpu_timer.c | 225 ++++
arch/riscv/kvm/vm.c | 81 ++
arch/riscv/kvm/vmid.c | 120 ++
drivers/clk/Kconfig | 5 +
drivers/clk/Makefile | 1 +
drivers/clk/microchip/Makefile | 2 +
drivers/clk/microchip/clk-pfsoc.c | 508 +++++++++
drivers/clocksource/timer-riscv.c | 8 +
include/clocksource/timer-riscv.h | 16 +
include/uapi/linux/kvm.h | 8 +
39 files changed, 5621 insertions(+), 54 deletions(-)
create mode 100644 arch/riscv/boot/dts/microchip/Makefile
create mode 100644 arch/riscv/boot/dts/microchip/icicle-kit-es.dts
create mode 100644 arch/riscv/configs/extra_debug.config
create mode 100644 arch/riscv/include/asm/kvm_host.h
create mode 100644 arch/riscv/include/asm/kvm_types.h
create mode 100644 arch/riscv/include/asm/kvm_vcpu_timer.h
create mode 100644 arch/riscv/include/uapi/asm/kvm.h
create mode 100644 arch/riscv/kvm/Kconfig
create mode 100644 arch/riscv/kvm/Makefile
create mode 100644 arch/riscv/kvm/main.c
create mode 100644 arch/riscv/kvm/mmu.c
create mode 100644 arch/riscv/kvm/tlb.S
create mode 100644 arch/riscv/kvm/vcpu.c
create mode 100644 arch/riscv/kvm/vcpu_exit.c
create mode 100644 arch/riscv/kvm/vcpu_sbi.c
create mode 100644 arch/riscv/kvm/vcpu_switch.S
create mode 100644 arch/riscv/kvm/vcpu_timer.c
create mode 100644 arch/riscv/kvm/vm.c
create mode 100644 arch/riscv/kvm/vmid.c
create mode 100644 drivers/clk/microchip/clk-pfsoc.c
create mode 100644 include/clocksource/timer-riscv.h
--
2.19.1
1
26
Andrew Donnellan (1):
powerpc: Fix __clear_user() with KUAP enabled
Christophe Leroy (2):
powerpc: Add a framework for user access tracking
powerpc: Implement user_access_begin and friends
Daniel Axtens (1):
powerpc/64s: move some exception handlers out of line
Nicholas Piggin (3):
powerpc/64s: flush L1D on kernel entry
powerpc/uaccess: Evaluate macro arguments once, before user access is
allowed
powerpc/64s: flush L1D after user accesses
.../admin-guide/kernel-parameters.txt | 7 +
.../powerpc/include/asm/book3s/64/kup-radix.h | 22 +++
arch/powerpc/include/asm/exception-64s.h | 9 +-
arch/powerpc/include/asm/feature-fixups.h | 19 +++
arch/powerpc/include/asm/futex.h | 4 +
arch/powerpc/include/asm/kup.h | 40 +++++
arch/powerpc/include/asm/security_features.h | 7 +
arch/powerpc/include/asm/setup.h | 4 +
arch/powerpc/include/asm/uaccess.h | 147 ++++++++++++++----
arch/powerpc/kernel/exceptions-64s.S | 96 +++++++-----
arch/powerpc/kernel/setup_64.c | 122 ++++++++++++++-
arch/powerpc/kernel/vmlinux.lds.S | 14 ++
arch/powerpc/lib/checksum_wrappers.c | 4 +
arch/powerpc/lib/feature-fixups.c | 104 +++++++++++++
arch/powerpc/lib/string_32.S | 4 +-
arch/powerpc/lib/string_64.S | 6 +-
arch/powerpc/platforms/powernv/setup.c | 17 ++
arch/powerpc/platforms/pseries/setup.c | 8 +
18 files changed, 553 insertions(+), 81 deletions(-)
create mode 100644 arch/powerpc/include/asm/book3s/64/kup-radix.h
create mode 100644 arch/powerpc/include/asm/kup.h
--
2.25.1
1
7
Andrew Donnellan (1):
powerpc: Fix __clear_user() with KUAP enabled
Christophe Leroy (3):
powerpc: Add a framework for user access tracking
powerpc: Implement user_access_begin and friends
powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
Daniel Axtens (1):
powerpc/64s: move some exception handlers out of line
David Edmondson (1):
KVM: x86: clflushopt should be treated as a no-op by emulation
Greg Kroah-Hartman (1):
Linux 4.19.159
Johannes Berg (1):
mac80211: always wind down STA state
Nicholas Piggin (3):
powerpc/64s: flush L1D on kernel entry
powerpc/uaccess: Evaluate macro arguments once, before user access is
allowed
powerpc/64s: flush L1D after user accesses
Nick Desaulniers (1):
ACPI: GED: fix -Wformat
Salvatore Bonaccorso (1):
Revert "perf cs-etm: Move definition of 'traceid_list' global variable
from header file"
Zhang Changzhong (1):
can: proc: can_remove_proc(): silence remove_proc_entry warning
.../admin-guide/kernel-parameters.txt | 7 +
Makefile | 2 +-
.../powerpc/include/asm/book3s/64/kup-radix.h | 22 +++
arch/powerpc/include/asm/exception-64s.h | 9 +-
arch/powerpc/include/asm/feature-fixups.h | 19 +++
arch/powerpc/include/asm/futex.h | 4 +
arch/powerpc/include/asm/kup.h | 40 +++++
arch/powerpc/include/asm/security_features.h | 7 +
arch/powerpc/include/asm/setup.h | 4 +
arch/powerpc/include/asm/uaccess.h | 147 ++++++++++++++----
arch/powerpc/kernel/exceptions-64s.S | 96 +++++++-----
arch/powerpc/kernel/head_8xx.S | 8 +-
arch/powerpc/kernel/setup_64.c | 122 ++++++++++++++-
arch/powerpc/kernel/vmlinux.lds.S | 14 ++
arch/powerpc/lib/checksum_wrappers.c | 4 +
arch/powerpc/lib/feature-fixups.c | 104 +++++++++++++
arch/powerpc/lib/string_32.S | 4 +-
arch/powerpc/lib/string_64.S | 6 +-
arch/powerpc/platforms/powernv/setup.c | 17 ++
arch/powerpc/platforms/pseries/setup.c | 8 +
arch/x86/kvm/emulate.c | 8 +-
drivers/acpi/evged.c | 2 +-
net/can/proc.c | 6 +-
net/mac80211/sta_info.c | 18 +++
tools/perf/util/cs-etm.c | 3 -
tools/perf/util/cs-etm.h | 3 +
26 files changed, 589 insertions(+), 95 deletions(-)
create mode 100644 arch/powerpc/include/asm/book3s/64/kup-radix.h
create mode 100644 arch/powerpc/include/asm/kup.h
--
2.25.1
1
14
From: Daniel Vetter <daniel.vetter(a)ffwll.ch>
stable inclusion
from linux-4.19.156
commit 6612b754ac0c85ca8b1181b5d3ea4461a8c1bbcb
CVE: CVE-2020-28974
--------------------------------
commit 3c4e0dff2095c579b142d5a0693257f1c58b4804 upstream.
It's buggy:
On Fri, Nov 06, 2020 at 10:30:08PM +0800, Minh Yuan wrote:
> We recently discovered a slab-out-of-bounds read in fbcon in the latest
> kernel ( v5.10-rc2 for now ). The root cause of this vulnerability is that
> "fbcon_do_set_font" did not handle "vc->vc_font.data" and
> "vc->vc_font.height" correctly, and the patch
> <https://lkml.org/lkml/2020/9/27/223> for VT_RESIZEX can't handle this
> issue.
>
> Specifically, we use KD_FONT_OP_SET to set a small font.data for tty6, and
> use KD_FONT_OP_SET again to set a large font.height for tty1. After that,
> we use KD_FONT_OP_COPY to assign tty6's vc_font.data to tty1's vc_font.data
> in "fbcon_do_set_font", while tty1 retains the original larger
> height. Obviously, this will cause an out-of-bounds read, because we can
> access a smaller vc_font.data with a larger vc_font.height.
Further there was only one user ever.
- Android's loadfont, busybox and console-tools only ever use OP_GET
and OP_SET
- fbset documentation only mentions the kernel cmdline font: option,
not anything else.
- systemd used OP_COPY before release 232 published in Nov 2016
Now unfortunately the crucial report seems to have gone down with
gmane, and the commit message doesn't say much. But the pull request
hints at OP_COPY being broken
https://github.com/systemd/systemd/pull/3651
So in other words, this never worked, and the only project which
foolishly every tried to use it, realized that rather quickly too.
Instead of trying to fix security issues here on dead code by adding
missing checks, fix the entire thing by removing the functionality.
Note that systemd code using the OP_COPY function ignored the return
value, so it doesn't matter what we're doing here really - just in
case a lone server somewhere happens to be extremely unlucky and
running an affected old version of systemd. The relevant code from
font_copy_to_all_vcs() in systemd was:
/* copy font from active VT, where the font was uploaded to */
cfo.op = KD_FONT_OP_COPY;
cfo.height = vcs.v_active-1; /* tty1 == index 0 */
(void) ioctl(vcfd, KDFONTOP, &cfo);
Note this just disables the ioctl, garbage collecting the now unused
callbacks is left for -next.
v2: Tetsuo found the old mail, which allowed me to find it on another
archive. Add the link too.
Acked-by: Peilin Ye <yepeilin.cs(a)gmail.com>
Reported-by: Minh Yuan <yuanmingbuaa(a)gmail.com>
References: https://lists.freedesktop.org/archives/systemd-devel/2016-June/036935.html
References: https://github.com/systemd/systemd/pull/3651
Cc: Greg KH <greg(a)kroah.com>
Cc: Peilin Ye <yepeilin.cs(a)gmail.com>
Cc: Tetsuo Handa <penguin-kernel(a)i-love.sakura.ne.jp>
Signed-off-by: Daniel Vetter <daniel.vetter(a)intel.com>
Link: https://lore.kernel.org/r/20201108153806.3140315-1-daniel.vetter@ffwll.ch
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/tty/vt/vt.c | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 758f522f331e..13ea0579f104 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4574,27 +4574,6 @@ static int con_font_default(struct vc_data *vc, struct console_font_op *op)
return rc;
}
-static int con_font_copy(struct vc_data *vc, struct console_font_op *op)
-{
- int con = op->height;
- int rc;
-
-
- console_lock();
- if (vc->vc_mode != KD_TEXT)
- rc = -EINVAL;
- else if (!vc->vc_sw->con_font_copy)
- rc = -ENOSYS;
- else if (con < 0 || !vc_cons_allocated(con))
- rc = -ENOTTY;
- else if (con == vc->vc_num) /* nothing to do */
- rc = 0;
- else
- rc = vc->vc_sw->con_font_copy(vc, con);
- console_unlock();
- return rc;
-}
-
int con_font_op(struct vc_data *vc, struct console_font_op *op)
{
switch (op->op) {
@@ -4605,7 +4584,8 @@ int con_font_op(struct vc_data *vc, struct console_font_op *op)
case KD_FONT_OP_SET_DEFAULT:
return con_font_default(vc, op);
case KD_FONT_OP_COPY:
- return con_font_copy(vc, op);
+ /* was buggy and never really used */
+ return -EINVAL;
}
return -ENOSYS;
}
--
2.25.1
1
0
[PATCH 1/3] fbdev, newport_con: Move FONT_EXTRA_WORDS macros into linux/font.h
by Yang Yingliang 23 Nov '20
by Yang Yingliang 23 Nov '20
23 Nov '20
From: Peilin Ye <yepeilin.cs(a)gmail.com>
stable inclusion
from linux-4.19.151
commit 7b9eaa7241ea2cfa580b854d461be72107a4b35c
CVE: CVE-2020-28915
It's prepare for fixing CVE-2020-28915.
--------------------------------
commit bb0890b4cd7f8203e3aa99c6d0f062d6acdaad27 upstream.
drivers/video/console/newport_con.c is borrowing FONT_EXTRA_WORDS macros
from drivers/video/fbdev/core/fbcon.h. To keep things simple, move all
definitions into <linux/font.h>.
Since newport_con now uses four extra words, initialize the fourth word in
newport_set_font() properly.
Cc: stable(a)vger.kernel.org
Signed-off-by: Peilin Ye <yepeilin.cs(a)gmail.com>
Reviewed-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Daniel Vetter <daniel.vetter(a)ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/7fb8bc9b0abc676ada6b7ac0e0bd4…
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/video/console/newport_con.c | 7 +------
drivers/video/fbdev/core/fbcon.h | 7 -------
drivers/video/fbdev/core/fbcon_rotate.c | 1 +
drivers/video/fbdev/core/tileblit.c | 1 +
include/linux/font.h | 8 ++++++++
5 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 7f2526b43b33..46a6e6568994 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -33,12 +33,6 @@
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
-/* borrowed from fbcon.c */
-#define REFCOUNT(fd) (((int *)(fd))[-1])
-#define FNTSIZE(fd) (((int *)(fd))[-2])
-#define FNTCHARCNT(fd) (((int *)(fd))[-3])
-#define FONT_EXTRA_WORDS 3
-
static unsigned char *font_data[MAX_NR_CONSOLES];
static struct newport_regs *npregs;
@@ -519,6 +513,7 @@ static int newport_set_font(int unit, struct console_font *op)
FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = op->charcount;
REFCOUNT(new_data) = 0; /* usage counter */
+ FNTSUM(new_data) = 0;
p = new_data;
for (i = 0; i < op->charcount; i++) {
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index ac11200fd2d5..609280281a47 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -152,13 +152,6 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
-/* Font */
-#define REFCOUNT(fd) (((int *)(fd))[-1])
-#define FNTSIZE(fd) (((int *)(fd))[-2])
-#define FNTCHARCNT(fd) (((int *)(fd))[-3])
-#define FNTSUM(fd) (((int *)(fd))[-4])
-#define FONT_EXTRA_WORDS 4
-
/*
* Scroll Method
*/
diff --git a/drivers/video/fbdev/core/fbcon_rotate.c b/drivers/video/fbdev/core/fbcon_rotate.c
index c0d445294aa7..ac72d4f85f7d 100644
--- a/drivers/video/fbdev/core/fbcon_rotate.c
+++ b/drivers/video/fbdev/core/fbcon_rotate.c
@@ -14,6 +14,7 @@
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
+#include <linux/font.h>
#include <asm/types.h>
#include "fbcon.h"
#include "fbcon_rotate.h"
diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
index eb664dbf96f6..adff8d6ffe6f 100644
--- a/drivers/video/fbdev/core/tileblit.c
+++ b/drivers/video/fbdev/core/tileblit.c
@@ -13,6 +13,7 @@
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
+#include <linux/font.h>
#include <asm/types.h>
#include "fbcon.h"
diff --git a/include/linux/font.h b/include/linux/font.h
index d6821769dd1e..0a3639a00b3a 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -57,4 +57,12 @@ extern const struct font_desc *get_default_font(int xres, int yres,
/* Max. length for the name of a predefined font */
#define MAX_FONT_NAME 32
+/* Extra word getters */
+#define REFCOUNT(fd) (((int *)(fd))[-1])
+#define FNTSIZE(fd) (((int *)(fd))[-2])
+#define FNTCHARCNT(fd) (((int *)(fd))[-3])
+#define FNTSUM(fd) (((int *)(fd))[-4])
+
+#define FONT_EXTRA_WORDS 4
+
#endif /* _VIDEO_FONT_H */
--
2.25.1
1
2
23 Nov '20
From: Samuel Thibault <samuel.thibault(a)ens-lyon.org>
mainline inclusion
from mainline-v5.10
commit d4122754442799187d5d537a9c039a49a67e57f1
category: bugfix
bugzilla: NA
CVE: CVE-2020-28941
--------------------------------
Speakup has only one speakup_tty variable to store the tty it is managing. This
makes sense since its codebase currently assumes that there is only one user who
controls the screen reading.
That however means that we have to forbid using the line discipline several
times, otherwise the second closure would try to free a NULL ldisc_data, leading to
general protection fault: 0000 [#1] SMP KASAN PTI
RIP: 0010:spk_ttyio_ldisc_close+0x2c/0x60
Call Trace:
tty_ldisc_release+0xa2/0x340
tty_release_struct+0x17/0xd0
tty_release+0x9d9/0xcc0
__fput+0x231/0x740
task_work_run+0x12c/0x1a0
do_exit+0x9b5/0x2230
? release_task+0x1240/0x1240
? __do_page_fault+0x562/0xa30
do_group_exit+0xd5/0x2a0
__x64_sys_exit_group+0x35/0x40
do_syscall_64+0x89/0x2b0
? page_fault+0x8/0x30
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Cc: stable(a)vger.kernel.org
Reported-by: 秦世松 <qinshisong1205(a)gmail.com>
Signed-off-by: Samuel Thibault <samuel.thibault(a)ens-lyon.org>
Tested-by: Shisong Qin <qinshisong1205(a)gmail.com>
Link: https://lore.kernel.org/r/20201110183541.fzgnlwhjpgqzjeth@function
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
drivers/accessibility/speakup/spk_ttyio.c
[yyl: spk_ttyio.c is in drivers/staging/ in kernel-4.19]
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/staging/speakup/spk_ttyio.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
index 93742dbdee77..6c754ddf1257 100644
--- a/drivers/staging/speakup/spk_ttyio.c
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -49,15 +49,25 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
+
+ mutex_lock(&speakup_tty_mutex);
+ if (speakup_tty) {
+ mutex_unlock(&speakup_tty_mutex);
+ return -EBUSY;
+ }
speakup_tty = tty;
ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
- if (!ldisc_data)
+ if (!ldisc_data) {
+ speakup_tty = NULL;
+ mutex_unlock(&speakup_tty_mutex);
return -ENOMEM;
+ }
sema_init(&ldisc_data->sem, 0);
ldisc_data->buf_free = true;
speakup_tty->disc_data = ldisc_data;
+ mutex_unlock(&speakup_tty_mutex);
return 0;
}
--
2.25.1
1
0
Al Viro (1):
don't dump the threads that had been already exiting when zapped.
Alexander Usyskin (1):
mei: protect mei_cl_mtu from null dereference
Anand Jain (1):
btrfs: dev-replace: fail mount if we don't have replace item with
target device
Anand K Mistry (1):
x86/speculation: Allow IBPB to be conditionally enabled on CPUs with
always-on STIBP
Andrew Jeffery (1):
ARM: 9019/1: kprobes: Avoid fortify_panic() when copying optprobe
template
Andy Shevchenko (1):
pinctrl: intel: Set default bias in case no particular value given
Ard Biesheuvel (1):
crypto: arm64/aes-modes - get rid of literal load of addend vector
Arnaldo Carvalho de Melo (1):
perf scripting python: Avoid declaring function pointers with a
visibility attribute
Arnaud de Turckheim (3):
gpio: pcie-idio-24: Fix irq mask when masking
gpio: pcie-idio-24: Fix IRQ Enable Register value
gpio: pcie-idio-24: Enable PEX8311 interrupts
Baolin Wang (1):
mfd: sprd: Add wakeup capability for PMIC IRQ
Billy Tsai (1):
pinctrl: aspeed: Fix GPI only function problem.
Bob Peterson (3):
gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
gfs2: Add missing truncate_inode_pages_final for sd_aspace
gfs2: check for live vs. read-only file system in gfs2_fitrim
Boris Protopopov (1):
Convert trailing spaces and periods in path components
Brian Foster (1):
xfs: flush new eof page on truncate to avoid post-eof corruption
Chen Zhou (1):
selinux: Fix error return code in sel_ib_pkey_sid_slow()
Chris Brandt (1):
usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
Christoph Hellwig (2):
nbd: fix a block_device refcount leak in nbd_release
xfs: fix a missing unlock on error in xfs_fs_map_blocks
Chunyan Zhang (1):
tick/common: Touch watchdog in tick_unfreeze() on all CPUs
Coiby Xu (2):
pinctrl: amd: use higher precision for 512 RtcClk
pinctrl: amd: fix incorrect way to disable debounce filter
Dan Carpenter (3):
ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
can: peak_usb: add range checking in decode operations
futex: Don't enable IRQs unconditionally in put_pi_state()
Darrick J. Wong (6):
xfs: set xefi_discard when creating a deferred agfl free log intent
item
xfs: fix scrub flagging rtinherit even if there is no rt device
xfs: fix flags argument to rmap lookup when converting shared file
rmaps
xfs: set the unwritten bit in rmap lookup flags in
xchk_bmap_get_rmapextents
xfs: fix rmap key and record comparison functions
xfs: fix brainos in the refcount scrubber's rmap fragment processor
Dinghao Liu (1):
btrfs: ref-verify: fix memory leak in btrfs_ref_tree_mod
Evan Nimmo (1):
of/address: Fix of_node memory leak in of_dma_is_coherent
Evan Quan (3):
drm/amdgpu: perform srbm soft reset always on SDMA resume
drm/amd/pm: perform SMC reset on suspend/hibernation
drm/amd/pm: do not use ixFEATURE_STATUS for checking smc running
Evgeny Novikov (1):
usb: gadget: goku_udc: fix potential crashes in probe
Filipe Manana (1):
Btrfs: fix missing error return if writeback for extent buffer never
started
Gao Xiang (1):
erofs: derive atime instead of leaving it empty
George Spelvin (1):
random32: make prandom_u32() output unpredictable
Greg Kroah-Hartman (1):
Linux 4.19.158
Hannes Reinecke (1):
scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
Heiner Kallweit (1):
r8169: fix potential skb double free in an error path
Jason A. Donenfeld (1):
netfilter: use actual socket sk rather than skb sk when routing harder
Jerry Snitselaar (1):
tpm_tis: Disable interrupts on ThinkPad T490s
Jing Xiangfeng (1):
thunderbolt: Add the missed ida_simple_remove() in ring_request_msix()
Jiri Olsa (1):
perf tools: Add missing swap for ino_generation
Joakim Zhang (1):
can: flexcan: remove FLEXCAN_QUIRK_DISABLE_MECR quirk for LS1021A
Johannes Berg (1):
mac80211: fix use of skb payload instead of header
Johannes Thumshirn (1):
btrfs: reschedule when cloning lots of extents
Josef Bacik (1):
btrfs: sysfs: init devices outside of the chunk_mutex
Joseph Qi (1):
ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
Kaixu Xia (1):
ext4: correctly report "not supported" for {usr,grp}jquota when
!CONFIG_QUOTA
Keita Suzuki (1):
scsi: hpsa: Fix memory leak in hpsa_init_one()
Mao Wenan (1):
net: Update window_clamp if SOCK_RCVBUF is set
Marc Kleine-Budde (1):
can: rx-offload: don't call kfree_skb() from IRQ context
Marc Zyngier (1):
genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY
Martin Schiller (1):
net/x25: Fix null-ptr-deref in x25_connect
Martin Willi (1):
vrf: Fix fast path output packet handling with async Netfilter rules
Masashi Honma (1):
ath9k_htc: Use appropriate rs_datalen type
Matteo Croce (2):
Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
reboot: fix overflow parsing reboot cpu number
Matthew Wilcox (Oracle) (1):
btrfs: fix potential overflow in cluster_pages_for_defrag on 32bit
arch
Michał Mirosław (1):
regulator: defer probe when trying to get voltage from unresolved
supply
Mika Westerberg (1):
thunderbolt: Fix memory leak if ida_simple_get() fails in
enumerate_services()
Olaf Hering (1):
hv_balloon: disable warning when floor reached
Oleksij Rempel (1):
can: can_create_echo_skb(): fix echo skb generation: always use
skb_clone()
Oliver Hartkopp (1):
can: dev: __can_get_echo_skb(): fix real payload length return value
for RTR frames
Oliver Herms (1):
IPv6: Set SIT tunnel hard_header_len to zero
Peter Zijlstra (1):
perf: Fix get_recursion_context()
Qian Cai (1):
s390/smp: move rcu_cpu_starting() earlier
Shin'ichiro Kawasaki (1):
uio: Fix use-after-free in uio_unregister_device()
Stefano Brivio (1):
netfilter: ipset: Update byte and packet counters regardless of
whether they match
Stefano Stabellini (1):
swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb"
Stephane Grosjean (2):
can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
can: peak_canfd: pucan_handle_can_rx(): fix echo management when
loopback is on
Suravee Suthikulpanit (1):
iommu/amd: Increase interrupt remapping table limit to 512 entries
Sven Van Asbroeck (1):
lan743x: fix "BUG: invalid wait context" when setting rx mode
Thinh Nguyen (2):
usb: dwc3: gadget: Continue to process pending requests
usb: dwc3: gadget: Reclaim extra TRBs after request completion
Thomas Zimmermann (1):
drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
Tommi Rantala (1):
selftests: proc: fix warning: _GNU_SOURCE redefined
Tyler Hicks (1):
tpm: efi: Don't create binary_bios_measurements file for an empty log
Ursula Braun (1):
net/af_iucv: fix null pointer dereference on shutdown
Vincent Mailhol (1):
can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ
context
Wang Hai (2):
cosa: Add missing kfree in error path of cosa_write
tipc: fix memory leak in tipc_topsrv_start()
Wengang Wang (1):
ocfs2: initialize ip_next_orphan
Ye Bin (1):
cfg80211: regulatory: Fix inconsistent format argument
Yoshihiro Shimoda (1):
mmc: renesas_sdhi_core: Add missing tmio_mmc_host_free() at remove
Yunsheng Lin (1):
net: sch_generic: fix the missing new qdisc assignment bug
Zeng Tao (1):
time: Prevent undefined behaviour in timespec64_to_ns()
Zhang Qilong (2):
vfio: platform: fix reference leak in vfio_platform_open
xhci: hisilicon: fix refercence leak in xhci_histb_probe
zhuoliang zhang (1):
net: xfrm: fix a race condition during allocing spi
Makefile | 2 +-
arch/arm/include/asm/kprobes.h | 22 +-
arch/arm/probes/kprobes/opt-arm.c | 18 +-
arch/arm64/crypto/aes-modes.S | 16 +-
arch/s390/kernel/smp.c | 3 +-
arch/x86/kernel/cpu/bugs.c | 52 +-
drivers/block/nbd.c | 1 +
drivers/char/random.c | 1 -
drivers/char/tpm/eventlog/efi.c | 5 +
drivers/char/tpm/tpm_tis.c | 29 +-
drivers/gpio/gpio-pcie-idio-24.c | 62 ++-
drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 27 +-
.../gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 4 +
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 +
drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 2 +
.../gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 29 +-
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 8 +
drivers/gpu/drm/gma500/psb_irq.c | 34 +-
drivers/hv/hv_balloon.c | 2 +-
drivers/iommu/amd_iommu_types.h | 6 +-
drivers/mfd/sprd-sc27xx-spi.c | 28 +-
drivers/misc/mei/client.h | 4 +-
drivers/mmc/host/renesas_sdhi_core.c | 1 +
drivers/net/can/dev.c | 14 +-
drivers/net/can/flexcan.c | 3 +-
drivers/net/can/peak_canfd/peak_canfd.c | 11 +-
drivers/net/can/rx-offload.c | 4 +-
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 51 +-
drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 48 +-
drivers/net/ethernet/microchip/lan743x_main.c | 12 +-
drivers/net/ethernet/microchip/lan743x_main.h | 3 -
drivers/net/ethernet/realtek/r8169.c | 3 +-
drivers/net/vrf.c | 92 +++-
drivers/net/wan/cosa.c | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +-
drivers/of/address.c | 4 +-
drivers/pinctrl/aspeed/pinctrl-aspeed.c | 7 +-
drivers/pinctrl/intel/pinctrl-intel.c | 8 +
drivers/pinctrl/pinctrl-amd.c | 6 +-
drivers/regulator/core.c | 2 +
drivers/scsi/device_handler/scsi_dh_alua.c | 9 +-
drivers/scsi/hpsa.c | 4 +-
drivers/staging/erofs/inode.c | 21 +-
drivers/thunderbolt/nhi.c | 19 +-
drivers/thunderbolt/xdomain.c | 1 +
drivers/uio/uio.c | 10 +-
drivers/usb/class/cdc-acm.c | 9 +
drivers/usb/dwc3/gadget.c | 32 +-
drivers/usb/gadget/udc/goku_udc.c | 2 +-
drivers/usb/host/xhci-histb.c | 2 +-
drivers/vfio/platform/vfio_platform_common.c | 3 +-
fs/btrfs/dev-replace.c | 26 +-
fs/btrfs/extent_io.c | 4 +
fs/btrfs/ioctl.c | 12 +-
fs/btrfs/ref-verify.c | 1 +
fs/btrfs/volumes.c | 33 +-
fs/cifs/cifs_unicode.c | 8 +-
fs/ext4/inline.c | 1 +
fs/ext4/super.c | 4 +-
fs/gfs2/rgrp.c | 5 +-
fs/gfs2/super.c | 1 +
fs/ocfs2/super.c | 1 +
fs/xfs/libxfs/xfs_alloc.c | 1 +
fs/xfs/libxfs/xfs_bmap.h | 2 +-
fs/xfs/libxfs/xfs_rmap.c | 2 +-
fs/xfs/libxfs/xfs_rmap_btree.c | 16 +-
fs/xfs/scrub/bmap.c | 2 +
fs/xfs/scrub/inode.c | 3 +-
fs/xfs/scrub/refcount.c | 8 +-
fs/xfs/xfs_iops.c | 10 +
fs/xfs/xfs_pnfs.c | 2 +-
include/linux/can/skb.h | 20 +-
include/linux/netfilter_ipv4.h | 2 +-
include/linux/netfilter_ipv6.h | 2 +-
include/linux/prandom.h | 36 +-
include/linux/time64.h | 4 +
kernel/dma/swiotlb.c | 6 +-
kernel/events/internal.h | 2 +-
kernel/exit.c | 5 +-
kernel/futex.c | 5 +-
kernel/irq/Kconfig | 1 +
kernel/reboot.c | 28 +-
kernel/time/itimer.c | 4 -
kernel/time/tick-common.c | 2 +
kernel/time/timer.c | 7 -
lib/random32.c | 462 +++++++++++-------
net/ipv4/netfilter.c | 12 +-
net/ipv4/netfilter/ipt_SYNPROXY.c | 2 +-
net/ipv4/netfilter/iptable_mangle.c | 2 +-
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 2 +-
net/ipv4/netfilter/nf_reject_ipv4.c | 2 +-
net/ipv4/netfilter/nft_chain_route_ipv4.c | 2 +-
net/ipv4/syncookies.c | 9 +-
net/ipv6/netfilter.c | 6 +-
net/ipv6/netfilter/ip6table_mangle.c | 2 +-
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 2 +-
net/ipv6/netfilter/nft_chain_route_ipv6.c | 2 +-
net/ipv6/sit.c | 2 -
net/ipv6/syncookies.c | 10 +-
net/iucv/af_iucv.c | 3 +-
net/mac80211/tx.c | 37 +-
net/netfilter/ipset/ip_set_core.c | 3 +-
net/netfilter/ipvs/ip_vs_core.c | 4 +-
net/sched/sch_generic.c | 3 +
net/tipc/topsrv.c | 10 +-
net/wireless/reg.c | 2 +-
net/x25/af_x25.c | 2 +-
net/xfrm/xfrm_state.c | 8 +-
security/selinux/ibpkey.c | 4 +-
sound/hda/ext/hdac_ext_controller.c | 2 +
.../scripting-engines/trace-event-python.c | 7 +-
tools/perf/util/session.c | 1 +
.../testing/selftests/proc/proc-loadavg-001.c | 1 -
.../selftests/proc/proc-self-syscall.c | 1 -
.../testing/selftests/proc/proc-uptime-002.c | 1 -
115 files changed, 1073 insertions(+), 539 deletions(-)
--
2.25.1
1
98
[PATCH 1/2] ascend: share_pool: support debug mode and refactor some functions
by Yang Yingliang 23 Nov '20
by Yang Yingliang 23 Nov '20
23 Nov '20
From: Ding Tianhong <dingtianhong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
The share pool is used widely for several accelerator, and it is
difficult to debug the user problem, so add debug mode to analyse
the problem, this mode is enabled by the sysctl_sp_debug_mode flag.
Some functions have been refactored to protect the critical area
correctly, and output message more clearly.
Signed-off-by: Tang Yizhou <tangyizhou(a)huawei.com>
Signed-off-by: Zhou Guanghui <zhouguanghui1(a)huawei.com>
Signed-off-by: Wu Peng <wupeng58(a)huawei.com>
Signed-off-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/share_pool.h | 15 +-
kernel/sysctl.c | 9 +
mm/share_pool.c | 537 +++++++++++++++++++++----------------
3 files changed, 326 insertions(+), 235 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h
index 09afbae33d41..2557ef138122 100644
--- a/include/linux/share_pool.h
+++ b/include/linux/share_pool.h
@@ -5,6 +5,7 @@
#include <linux/mm_types.h>
#include <linux/notifier.h>
#include <linux/vmalloc.h>
+#include <linux/printk.h>
#define SP_HUGEPAGE (1 << 0)
#define SP_HUGEPAGE_ONLY (1 << 1)
@@ -35,6 +36,8 @@ extern int sysctl_share_pool_hugepage_enable;
extern int sysctl_ac_mode;
+extern int sysctl_sp_debug_mode;
+
extern int enable_ascend_share_pool;
/* Processes in the same sp_group can share memory.
@@ -70,7 +73,7 @@ struct sp_group {
/* number of sp_area */
atomic_t spa_num;
/* total size of all sp_area from sp_alloc and k2u(spg) */
- atomic_t size;
+ atomic64_t size;
/* record the number of hugepage allocation failures */
int hugepage_failures;
/* is_alive == false means it's being destroyed */
@@ -211,6 +214,12 @@ static inline bool sp_mmap_check(unsigned long flags)
return false;
}
+static inline void sp_dump_stack(void)
+{
+ if (sysctl_sp_debug_mode)
+ dump_stack();
+}
+
#else
static inline int sp_group_add_task(int pid, int spg_id)
@@ -349,6 +358,10 @@ static inline bool sp_mmap_check(unsigned long flags)
{
return false;
}
+
+static inline void sp_dump_stack(void)
+{
+}
#endif
#endif /* LINUX_SHARE_POOL_H */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 61e62f1ccee4..26c215fb37dc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1737,6 +1737,15 @@ static struct ctl_table vm_table[] = {
.extra1 = &zero,
.extra2 = &one,
},
+ {
+ .procname = "sharepool_debug_mode",
+ .data = &sysctl_sp_debug_mode,
+ .maxlen = sizeof(sysctl_sp_debug_mode),
+ .mode = 0600,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
#endif
{ }
};
diff --git a/mm/share_pool.c b/mm/share_pool.c
index fcbc831f7f8c..24c5dd680451 100644
--- a/mm/share_pool.c
+++ b/mm/share_pool.c
@@ -57,6 +57,8 @@ static const int mdc_default_group_id = 1;
/* access control mode */
int sysctl_ac_mode = AC_NONE;
+/* debug mode */
+int sysctl_sp_debug_mode;
/* idr of all sp_groups */
static DEFINE_IDR(sp_group_idr);
@@ -85,9 +87,11 @@ struct sp_proc_stat {
/* for kthread buff_module_guard_work */
static struct sp_proc_stat kthread_stat = {0};
-/* The caller must hold sp_mutex. */
-static struct sp_proc_stat *sp_init_proc_stat(struct task_struct *tsk)
-{
+/*
+ * The caller must hold sp_mutex and ensure no concurrency problem
+ * for task_struct and mm_struct.
+ */
+static struct sp_proc_stat *sp_init_proc_stat(struct task_struct *tsk) {
struct sp_proc_stat *stat;
int id = tsk->mm->sp_stat_id;
int tgid = tsk->tgid;
@@ -138,7 +142,7 @@ static struct sp_spa_stat spa_stat = {0};
/* statistics of all sp group born from sp_alloc and k2u(spg) */
struct sp_spg_stat {
atomic_t spa_total_num;
- atomic_t spa_total_size;
+ atomic64_t spa_total_size;
};
static struct sp_spg_stat spg_stat = {0};
@@ -166,10 +170,11 @@ struct sp_area {
struct list_head link; /* link to the spg->head */
struct sp_group *spg;
enum spa_type type; /* where spa born from */
+ struct mm_struct *mm; /* owner of k2u(task) */
};
static DEFINE_SPINLOCK(sp_area_lock);
static struct rb_root sp_area_root = RB_ROOT;
-bool host_svm_sp_enable = false;
+static bool host_svm_sp_enable = false;
int sysctl_share_pool_hugepage_enable = 1;
@@ -241,7 +246,7 @@ static int spa_dec_usage(enum spa_type type, unsigned long size)
return 0;
}
-static void *sp_mmap(struct mm_struct *mm, struct file *file,
+static unsigned long sp_mmap(struct mm_struct *mm, struct file *file,
struct sp_area *spa, unsigned long *populate);
static void free_sp_group(struct sp_group *spg)
@@ -274,7 +279,18 @@ static struct sp_group *__sp_find_spg(int pid, int spg_id)
if (ret)
return NULL;
- spg = tsk->mm->sp_group;
+ /*
+ * Once we encounter a concurrency problem here.
+ * To fix it, we believe get_task_mm() and mmput() is too
+ * heavy because we just get the pointer of sp_group.
+ */
+ task_lock(tsk);
+ if (tsk->mm == NULL)
+ spg = NULL;
+ else
+ spg = tsk->mm->sp_group;
+ task_unlock(tsk);
+
put_task_struct(tsk);
} else {
spg = idr_find(&sp_group_idr, spg_id);
@@ -318,7 +334,7 @@ static struct sp_group *find_or_alloc_sp_group(int spg_id)
}
spg->id = spg_id;
atomic_set(&spg->spa_num, 0);
- atomic_set(&spg->size, 0);
+ atomic64_set(&spg->size, 0);
spg->is_alive = true;
spg->hugepage_failures = 0;
spg->dvpp_multi_spaces = false;
@@ -377,9 +393,6 @@ static void sp_munmap_task_areas(struct mm_struct *mm, struct list_head *stop)
struct sp_area *spa, *prev = NULL;
int err;
- if (!mmget_not_zero(mm))
- return;
- down_write(&mm->mmap_sem);
spin_lock(&sp_area_lock);
list_for_each_entry(spa, &mm->sp_group->spa_list, link) {
@@ -406,8 +419,17 @@ static void sp_munmap_task_areas(struct mm_struct *mm, struct list_head *stop)
__sp_area_drop_locked(prev);
spin_unlock(&sp_area_lock);
- up_write(&mm->mmap_sem);
- mmput(mm);
+}
+
+/* The caller must hold sp_mutex. */
+static void __sp_group_drop_locked(struct sp_group *spg)
+{
+ bool is_alive = spg->is_alive;
+
+ if (atomic_dec_and_test(&spg->use_count)) {
+ BUG_ON(is_alive);
+ free_sp_group(spg);
+ }
}
/**
@@ -446,8 +468,9 @@ int sp_group_add_task(int pid, int spg_id)
spg = idr_find(&sp_group_idr, spg_id);
if (!spg_valid(spg)) {
mutex_unlock(&sp_mutex);
- pr_err("share pool: task add group failed because group id %d hasn't been create or dead\n",
- spg_id);
+ if (printk_ratelimit())
+ pr_err("share pool: task add group failed because group id %d "
+ "hasn't been create or dead\n", spg_id);
return -EINVAL;
}
mutex_unlock(&sp_mutex);
@@ -457,7 +480,9 @@ int sp_group_add_task(int pid, int spg_id)
spg_id = ida_alloc_range(&sp_group_id_ida, SPG_ID_AUTO_MIN,
SPG_ID_AUTO_MAX, GFP_ATOMIC);
if (spg_id < 0) {
- pr_err("share pool: task add group failed when automatically generate group id failed\n");
+ if (printk_ratelimit())
+ pr_err("share pool: task add group failed when automatically "
+ "generate group id failed\n");
return spg_id;
}
}
@@ -467,8 +492,9 @@ int sp_group_add_task(int pid, int spg_id)
SPG_ID_DVPP_PASS_THROUGH_MIN,
SPG_ID_DVPP_PASS_THROUGH_MAX, GFP_ATOMIC);
if (spg_id < 0) {
- pr_err("share pool: task add group failed when automatically generate group id failed"
- "in DVPP pass through\n");
+ if (printk_ratelimit())
+ pr_err("share pool: task add group failed when automatically "
+ "generate group id failed in DVPP pass through\n");
return spg_id;
}
}
@@ -494,25 +520,31 @@ int sp_group_add_task(int pid, int spg_id)
ret = PTR_ERR(spg);
goto out_put_task;
}
+ atomic_inc(&spg->use_count);
+
/* access control permission check */
if (sysctl_ac_mode == AC_SINGLE_OWNER) {
if (spg->owner != current->group_leader) {
ret = -EPERM;
- goto out_put_task;
+ goto out_drop_group;
}
}
+ mm = get_task_mm(tsk);
+ if (!mm) {
+ ret = -ESRCH;
+ goto out_drop_group;
+ }
+
/* per process statistics initialization */
stat = sp_init_proc_stat(tsk);
if (IS_ERR(stat)) {
ret = PTR_ERR(stat);
pr_err("share pool: init proc stat failed, ret %lx\n", PTR_ERR(stat));
- goto out_put_task;
+ goto out_put_mm;
}
- mm = tsk->mm;
mm->sp_group = spg;
- atomic_inc(&spg->use_count);
list_add_tail(&tsk->mm->sp_node, &spg->procs);
/*
* create mappings of existing shared memory segments into this
@@ -523,7 +555,7 @@ int sp_group_add_task(int pid, int spg_id)
list_for_each_entry(spa, &spg->spa_list, link) {
unsigned long populate = 0;
struct file *file = spa_file(spa);
- void *p;
+ unsigned long addr;
if (prev)
__sp_area_drop_locked(prev);
@@ -532,28 +564,24 @@ int sp_group_add_task(int pid, int spg_id)
atomic_inc(&spa->use_count);
spin_unlock(&sp_area_lock);
- p = sp_mmap(mm, file, spa, &populate);
- if (IS_ERR(p) && (PTR_ERR(p) != -ESPGMMEXIT)) {
+ down_write(&mm->mmap_sem);
+ addr = sp_mmap(mm, file, spa, &populate);
+ if (IS_ERR_VALUE(addr)) {
sp_munmap_task_areas(mm, &spa->link);
- ret = PTR_ERR(p);
+ up_write(&mm->mmap_sem);
+ ret = addr;
pr_err("share pool: task add group sp mmap failed, ret %d\n", ret);
spin_lock(&sp_area_lock);
break;
}
-
- if (PTR_ERR(p) == -ESPGMMEXIT) {
- pr_err("share pool: task add group sp mmap failed, ret -ESPGMEXIT\n");
- spin_lock(&sp_area_lock);
- ret = -ESPGMMEXIT;
- break;
- }
+ up_write(&mm->mmap_sem);
if (populate) {
ret = do_mm_populate(mm, spa->va_start, populate, 0);
if (ret) {
if (printk_ratelimit())
- pr_err("share pool: task add group failed when mm populate failed: %d\n",
- ret);
+ pr_warn("share pool: task add group failed when mm populate "
+ "failed (potential no enough memory): %d\n", ret);
sp_munmap_task_areas(mm, spa->link.next);
}
}
@@ -567,8 +595,16 @@ int sp_group_add_task(int pid, int spg_id)
if (unlikely(ret)) {
idr_remove(&sp_stat_idr, mm->sp_stat_id);
kfree(stat);
+ mm->sp_stat_id = 0;
+ list_del(&mm->sp_node);
+ mm->sp_group = NULL;
}
+out_put_mm:
+ mmput(mm);
+out_drop_group:
+ if (unlikely(ret))
+ __sp_group_drop_locked(spg);
out_put_task:
put_task_struct(tsk);
out_unlock:
@@ -609,9 +645,6 @@ void sp_group_exit(struct mm_struct *mm)
bool is_alive = true;
bool unlock;
- if (!enable_ascend_share_pool)
- return;
-
/*
* Nothing to do if this thread group doesn't belong to any sp_group.
* No need to protect this check with lock because we can add a task
@@ -638,18 +671,13 @@ void sp_group_exit(struct mm_struct *mm)
void sp_group_post_exit(struct mm_struct *mm)
{
- bool is_alive;
struct sp_proc_stat *stat;
bool unlock;
- if (!enable_ascend_share_pool)
- return;
-
if (!mm->sp_group)
return;
spg_exit_lock(&unlock);
- is_alive = mm->sp_group->is_alive;
/* pointer stat must be valid, we don't need to check sanity */
stat = idr_find(&sp_stat_idr, mm->sp_stat_id);
@@ -673,10 +701,7 @@ void sp_group_post_exit(struct mm_struct *mm)
idr_remove(&sp_stat_idr, mm->sp_stat_id);
- if (atomic_dec_and_test(&mm->sp_group->use_count)) {
- BUG_ON(is_alive);
- free_sp_group(mm->sp_group);
- }
+ __sp_group_drop_locked(mm->sp_group);
spg_exit_unlock(unlock);
kfree(stat);
@@ -716,7 +741,7 @@ static void __insert_sp_area(struct sp_area *spa)
static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
struct sp_group *spg, enum spa_type type)
{
- struct sp_area *spa;
+ struct sp_area *spa, *err;
struct rb_node *n;
unsigned long vstart = MMAP_SHARE_POOL_START;
unsigned long vend = MMAP_SHARE_POOL_16G_START;
@@ -728,6 +753,11 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
vstart = MMAP_SHARE_POOL_16G_START;
vend = MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE;
} else {
+ if (!spg) {
+ if (printk_ratelimit())
+ pr_err("share pool: don't allow k2u(task) in host svm multiprocess scene\n");
+ return ERR_PTR(-EINVAL);
+ }
vstart = spg->dvpp_va_start;
vend = spg->dvpp_va_start + spg->dvpp_size;
}
@@ -735,14 +765,11 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
addr = vstart;
- if (!sysctl_share_pool_hugepage_enable)
- flags &= ~(SP_HUGEPAGE_ONLY | SP_HUGEPAGE);
-
spa = kmalloc(sizeof(struct sp_area), GFP_KERNEL);
if (unlikely(!spa)) {
if (printk_ratelimit())
pr_err("share pool: alloc spa failed due to lack of memory\n");
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
spin_lock(&sp_area_lock);
@@ -788,6 +815,7 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
}
found:
if (addr + size_align > vend) {
+ err = ERR_PTR(-EOVERFLOW);
goto error;
}
@@ -799,15 +827,17 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
atomic_set(&spa->use_count, 1);
spa->type = type;
- if (spa_inc_usage(type, size))
+ if (spa_inc_usage(type, size)) {
+ err = ERR_PTR(-EINVAL);
goto error;
+ }
__insert_sp_area(spa);
if (spa->spg) {
atomic_inc(&spg->spa_num);
- atomic_add(size, &spg->size);
+ atomic64_add(size, &spg->size);
atomic_inc(&spg_stat.spa_total_num);
- atomic_add(size, &spg_stat.spa_total_size);
+ atomic64_add(size, &spg_stat.spa_total_size);
list_add_tail(&spa->link, &spg->spa_list);
}
spin_unlock(&sp_area_lock);
@@ -817,7 +847,7 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags,
error:
spin_unlock(&sp_area_lock);
kfree(spa);
- return NULL;
+ return err;
}
/* the caller should hold sp_area_lock */
@@ -862,9 +892,9 @@ static void sp_free_area(struct sp_area *spa)
spa_dec_usage(spa->type, spa->real_size); /* won't fail */
if (spa->spg) {
atomic_dec(&spa->spg->spa_num);
- atomic_sub(spa->real_size, &spa->spg->size);
+ atomic64_sub(spa->real_size, &spa->spg->size);
atomic_dec(&spg_stat.spa_total_num);
- atomic_sub(spa->real_size, &spg_stat.spa_total_size);
+ atomic64_sub(spa->real_size, &spg_stat.spa_total_size);
list_del(&spa->link);
}
rb_erase(&spa->rb_node, &sp_area_root);
@@ -898,7 +928,7 @@ void sp_area_drop(struct vm_area_struct *vma)
{
struct sp_area *spa;
- if (!sp_check_vm_share_pool(vma->vm_flags))
+ if (!(vma->vm_flags & VM_SHARE_POOL))
return;
/*
@@ -979,13 +1009,25 @@ int sp_free(unsigned long addr)
} else { /* spa == NULL */
ret = -EINVAL;
if (printk_ratelimit())
- pr_err("share pool: sp_free invalid input addr %pK\n", (void *)addr);
+ pr_err("share pool: sp free invalid input addr %pK\n", (void *)addr);
goto out;
}
+ if (spa->type != SPA_TYPE_ALLOC) {
+ if (printk_ratelimit())
+ pr_err("share pool: sp free failed, addr %pK is not from sp_alloc\n",
+ (void *)addr);
+ }
+
if (!spg_valid(spa->spg))
goto drop_spa;
+ pr_notice("share pool: [sp free] caller %s(%d/%d); "
+ "group id %d addr 0x%pK, size %ld\n",
+ current->comm, current->tgid, current->pid, spa->spg->id,
+ (void *)spa->va_start, spa->real_size);
+ sp_dump_stack();
+
__sp_free(spa->spg, spa->va_start, spa_size(spa), NULL);
/* Free the memory of the backing shmem or hugetlbfs */
@@ -993,7 +1035,7 @@ int sp_free(unsigned long addr)
offset = addr - MMAP_SHARE_POOL_START;
ret = vfs_fallocate(spa_file(spa), mode, offset, spa_size(spa));
if (ret)
- pr_err("share pool: fallocate failed: %d\n", ret);
+ pr_err("share pool: sp free fallocate failed: %d\n", ret);
/* pointer stat may be invalid because of kthread buff_module_guard_work */
if (current->mm == NULL) {
@@ -1016,7 +1058,7 @@ int sp_free(unsigned long addr)
EXPORT_SYMBOL_GPL(sp_free);
/* wrapper of __do_mmap() and the caller must hold down_write(&mm->mmap_sem). */
-static unsigned long __sp_mmap(struct mm_struct *mm, struct file *file,
+static unsigned long sp_mmap(struct mm_struct *mm, struct file *file,
struct sp_area *spa, unsigned long *populate)
{
unsigned long addr = spa->va_start;
@@ -1033,30 +1075,13 @@ static unsigned long __sp_mmap(struct mm_struct *mm, struct file *file,
if (IS_ERR_VALUE(addr)) {
atomic_dec(&spa->use_count);
pr_err("share pool: do_mmap fails %ld\n", addr);
+ } else {
+ BUG_ON(addr != spa->va_start);
}
return addr;
}
-static void *sp_mmap(struct mm_struct *mm, struct file *file,
- struct sp_area *spa, unsigned long *populate)
-{
- unsigned long addr;
-
- if (!mmget_not_zero(mm))
- return ERR_PTR(-ESPGMMEXIT);
- down_write(&mm->mmap_sem);
- addr = __sp_mmap(mm, file, spa, populate);
- up_write(&mm->mmap_sem);
- mmput(mm);
-
- if (IS_ERR_VALUE(addr))
- return ERR_PTR(addr);
-
- BUG_ON(addr != spa->va_start);
- return (void *)addr;
-}
-
/**
* Allocate shared memory for all the processes in the same sp_group
* size - the size of memory to allocate
@@ -1071,12 +1096,14 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
struct sp_area *spa = NULL;
struct sp_proc_stat *stat;
unsigned long sp_addr;
- void *p_mmap, *p = ERR_PTR(-ENODEV);
+ unsigned long mmap_addr;
+ void *p = ERR_PTR(-ENODEV);
struct mm_struct *mm;
struct file *file;
unsigned long size_aligned;
int ret = 0;
struct mm_struct *tmp;
+ unsigned long mode, offset;
/* mdc scene hack */
if (enable_mdc_default_group)
@@ -1133,9 +1160,6 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
goto out;
}
- if (!sysctl_share_pool_hugepage_enable)
- sp_flags &= ~(SP_HUGEPAGE_ONLY | SP_HUGEPAGE);
-
if (sp_flags & SP_HUGEPAGE) {
file = spg->file_hugetlb;
size_aligned = ALIGN(size, PMD_SIZE);
@@ -1145,10 +1169,12 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
}
try_again:
spa = sp_alloc_area(size_aligned, sp_flags, spg, SPA_TYPE_ALLOC);
- if (!spa) {
+ if (IS_ERR(spa)) {
if (printk_ratelimit())
- pr_err("share pool: allocation failed due to alloc spa failure\n");
- p = ERR_PTR(-ENOMEM);
+ pr_err("share pool: allocation failed due to alloc spa failure "
+ "(potential no enough virtual memory when -75): %ld\n",
+ PTR_ERR(spa));
+ p = spa;
goto out;
}
sp_addr = spa->va_start;
@@ -1158,33 +1184,34 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
unsigned long populate = 0;
struct vm_area_struct *vma;
- p_mmap = sp_mmap(mm, file, spa, &populate);
- if (IS_ERR(p_mmap) && (PTR_ERR(p_mmap) != -ESPGMMEXIT)) {
- p = p_mmap;
+ if (!mmget_not_zero(mm))
+ continue;
+
+ down_write(&mm->mmap_sem);
+ mmap_addr = sp_mmap(mm, file, spa, &populate);
+ if (IS_ERR_VALUE(mmap_addr)) {
+ up_write(&mm->mmap_sem);
+ p = (void *)mmap_addr;
__sp_free(spg, sp_addr, size_aligned, mm);
- pr_err("share pool: allocation sp mmap failed, ret %ld\n", PTR_ERR(p_mmap));
- break;
+ mmput(mm);
+ pr_err("share pool: allocation sp mmap failed, ret %ld\n", mmap_addr);
+ goto out;
}
- if (PTR_ERR(p_mmap) == -ESPGMMEXIT) {
- pr_info("share pool: allocation sp mmap failed, ret -ESPGMMEXIT\n");
+ p =(void *)mmap_addr; /* success */
+ if (populate == 0) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
continue;
}
- p = p_mmap; /* success */
- if (populate == 0)
- continue;
-
- if (!mmget_not_zero(mm))
- continue;
- down_write(&mm->mmap_sem);
vma = find_vma(mm, sp_addr);
if (unlikely(!vma)) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
pr_err("share pool: allocation failed due to find %pK vma failure\n",
(void *)sp_addr);
p = ERR_PTR(-EINVAL);
- up_write(&mm->mmap_sem);
- mmput(mm);
goto out;
}
/* clean PTE_RDONLY flags or trigger SMMU event */
@@ -1216,9 +1243,17 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
}
if (printk_ratelimit())
- pr_err("share pool: allocation failed due to mm populate failed: %d\n",
- ret);
+ pr_warn("share pool: allocation failed due to mm populate failed"
+ "(potential no enough memory when -12): %d\n", ret);
p = ERR_PTR(ret);
+ __sp_area_drop(spa);
+
+ mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE;
+ offset = sp_addr - MMAP_SHARE_POOL_START;
+ ret = vfs_fallocate(spa_file(spa), mode, offset, spa_size(spa));
+ if (ret)
+ pr_err("share pool: fallocate failed %d\n", ret);
+
mmput(mm);
break;
}
@@ -1235,24 +1270,20 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
mutex_unlock(&sp_mutex);
/* this will free spa if mmap failed */
- if (spa)
+ if (spa && !IS_ERR(spa))
__sp_area_drop(spa);
+ if (!IS_ERR(p)) {
+ pr_notice("share pool: [sp alloc] caller %s(%d/%d); group id %d; "
+ "return addr 0x%pK, size %ld\n",
+ current->comm, current->tgid, current->pid, spa->spg->id,
+ (void *)spa->va_start, spa->real_size);
+ sp_dump_stack();
+ }
return p;
}
EXPORT_SYMBOL_GPL(sp_alloc);
-static unsigned long __sp_remap_get_pfn(unsigned long kva)
-{
- unsigned long pfn;
- if (is_vmalloc_addr((void *)kva))
- pfn = vmalloc_to_pfn((void *)kva);
- else
- pfn = virt_to_pfn(kva);
-
- return pfn;
-}
-
/*
* return value: >0 means this is a hugepage addr
* =0 means a normal addr. <0 means an errno.
@@ -1286,7 +1317,6 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
struct vm_area_struct *vma;
unsigned long ret_addr;
unsigned long populate = 0;
- unsigned long addr, buf, offset;
struct file *file = NULL;
int ret = 0;
struct user_struct *user = NULL;
@@ -1307,7 +1337,7 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
}
down_write(&mm->mmap_sem);
- ret_addr = __sp_mmap(mm, file, spa, &populate);
+ ret_addr = sp_mmap(mm, file, spa, &populate);
if (IS_ERR_VALUE(ret_addr)) {
pr_err("share pool: k2u mmap failed %lx\n", ret_addr);
goto out;
@@ -1326,20 +1356,12 @@ static unsigned long sp_remap_kva_to_vma(unsigned long kva, struct sp_area *spa,
goto out;
}
} else {
- buf = ret_addr;
- addr = kva;
- offset = 0;
- do {
- ret = remap_pfn_range(vma, buf, __sp_remap_get_pfn(addr), PAGE_SIZE,
- __pgprot(vma->vm_page_prot.pgprot));
- if (ret) {
- ret_addr = ret;
- goto out;
- }
- offset += PAGE_SIZE;
- buf += PAGE_SIZE;
- addr += PAGE_SIZE;
- } while (offset < spa_size(spa));
+ ret = remap_vmalloc_range(vma, (void *)kva, 0);
+ if (ret) {
+ pr_err("share pool: remap vmalloc failed, ret %d\n", ret);
+ ret_addr = ret;
+ goto out;
+ }
}
out:
@@ -1380,6 +1402,13 @@ static void *sp_make_share_kva_to_task(unsigned long kva, struct sp_area *spa,
}
p = (void *)ret_addr;
+
+ task_lock(tsk);
+ if (tsk->mm == NULL)
+ p = ERR_PTR(-ESRCH);
+ else
+ spa->mm = tsk->mm;
+ task_unlock(tsk);
out:
put_task_struct(tsk);
return p;
@@ -1438,6 +1467,7 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
unsigned long kva_aligned;
unsigned long size_aligned;
unsigned int page_size = PAGE_SIZE;
+ enum spa_type type;
int ret;
if (sp_flags & ~SP_DVPP) {
@@ -1453,6 +1483,7 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
} else if (ret == 0) {
/* do nothing */
} else {
+ pr_err("it is not vmalloc address\n");
return ERR_PTR(ret);
}
/* aligned down kva is convenient for caller to start with any valid kva */
@@ -1460,24 +1491,42 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
size_aligned = ALIGN(kva + size, page_size) - kva_aligned;
mutex_lock(&sp_mutex);
- spg = __sp_find_spg(pid, spg_id);
+ spg = __sp_find_spg(pid, SPG_ID_DEFAULT);
if (spg == NULL) {
- spa = sp_alloc_area(size_aligned, sp_flags, NULL, SPA_TYPE_K2TASK);
- if (!spa) {
+ type = SPA_TYPE_K2TASK;
+ if (spg_id != SPG_ID_NONE && spg_id != SPG_ID_DEFAULT) {
mutex_unlock(&sp_mutex);
if (printk_ratelimit())
- pr_err("share pool: k2u failed due to alloc spa failure\n");
- return ERR_PTR(-ENOMEM);
+ pr_err("share pool: k2task invalid spg id %d\n", spg_id);
+ return ERR_PTR(-EINVAL);
+ }
+ spa = sp_alloc_area(size_aligned, sp_flags, NULL, type);
+ if (IS_ERR(spa)) {
+ mutex_unlock(&sp_mutex);
+ if (printk_ratelimit())
+ pr_err("share pool: k2u(task) failed due to alloc spa failure "
+ "(potential no enough virtual memory when -75): %ld\n",
+ PTR_ERR(spa));
+ return spa;
}
uva = sp_make_share_kva_to_task(kva_aligned, spa, pid);
mutex_unlock(&sp_mutex);
} else if (spg_valid(spg)) {
- spa = sp_alloc_area(size_aligned, sp_flags, spg, SPA_TYPE_K2SPG);
- if (!spa) {
+ type = SPA_TYPE_K2SPG;
+ if (spg_id != SPG_ID_DEFAULT && spg_id != spg->id) {
mutex_unlock(&sp_mutex);
if (printk_ratelimit())
- pr_err("share pool: k2u failed due to alloc spa failure\n");
- return ERR_PTR(-ENOMEM);
+ pr_err("share pool: k2spg invalid spg id %d\n", spg_id);
+ return ERR_PTR(-EINVAL);
+ }
+ spa = sp_alloc_area(size_aligned, sp_flags, spg, type);
+ if (IS_ERR(spa)) {
+ mutex_unlock(&sp_mutex);
+ if (printk_ratelimit())
+ pr_err("share pool: k2u(spg) failed due to alloc spa failure "
+ "(potential no enough virtual memory when -75): %ld\n",
+ PTR_ERR(spa));
+ return spa;
}
uva = sp_make_share_kva_to_spg(kva_aligned, spa, spg);
@@ -1492,6 +1541,17 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size,
uva = uva + (kva - kva_aligned);
__sp_area_drop(spa);
+
+ if (!IS_ERR(uva)) {
+ if (spg_valid(spa->spg))
+ spg_id = spa->spg->id;
+ pr_notice("share pool: [sp k2u type %d] caller %s(%d/%d); group id %d; "
+ "return addr 0x%pK size %ld\n",
+ type, current->comm, current->tgid, current->pid, spg_id,
+ (void *)spa->va_start, spa->real_size);
+ sp_dump_stack();
+ }
+
return uva;
}
EXPORT_SYMBOL_GPL(sp_make_share_k2u);
@@ -1531,7 +1591,8 @@ static int sp_pte_hole(unsigned long start, unsigned long end,
struct mm_walk *walk)
{
if (printk_ratelimit())
- pr_err("share pool: hole [%pK, %pK) appeared unexpectedly\n", (void *)start, (void *)end);
+ pr_err("share pool: hole [%pK, %pK) appeared unexpectedly\n",
+ (void *)start, (void *)end);
return -EFAULT;
}
@@ -1545,7 +1606,8 @@ static int sp_hugetlb_entry(pte_t *ptep, unsigned long hmask,
if (unlikely(!pte_present(pte))) {
if (printk_ratelimit())
- pr_err("share pool: the page of addr %pK unexpectedly not in RAM\n", (void *)addr);
+ pr_err("share pool: the page of addr %pK unexpectedly "
+ "not in RAM\n", (void *)addr);
return -EFAULT;
}
@@ -1758,6 +1820,11 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
}
}
+ if (spa->type != SPA_TYPE_K2TASK && spa->type != SPA_TYPE_K2SPG) {
+ pr_err("share pool: this spa should not be unshare here\n");
+ ret = -EINVAL;
+ goto out_drop_area;
+ }
/*
* 1. overflow actually won't happen due to an spa must be valid.
* 2. we must unshare [spa->va_start, spa->va_start + spa->real_size) completely
@@ -1771,32 +1838,57 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
if (size_aligned < ALIGN(size, page_size)) {
ret = -EINVAL;
if (printk_ratelimit())
- pr_err("share pool: unshare uva failed due to invalid parameter size %lu\n", size);
+ pr_err("share pool: unshare uva failed due to invalid parameter size %lu\n",
+ size);
goto out_drop_area;
}
- if (spg_id == SPG_ID_NONE) {
- if (spa->spg) {
- ret = -EINVAL;
+ if (spa->type == SPA_TYPE_K2TASK) {
+ if (spg_id != SPG_ID_NONE && spg_id != SPG_ID_DEFAULT) {
if (printk_ratelimit())
- pr_err("share pool: unshare uva failed, SPG_ID_NONE is invalid\n");
+ pr_err("share pool: unshare uva(to task) failed, "
+ "invalid spg id %d\n", spg_id);
+ ret = -EINVAL;
goto out_drop_area;
}
rcu_read_lock();
tsk = find_task_by_vpid(pid);
- if (!tsk || (tsk->flags & PF_EXITING))
- ret = -ESRCH;
- else
- get_task_struct(tsk);
-
+ if (!tsk || !tsk->mm || (tsk->flags & PF_EXITING)) {
+ if (printk_ratelimit())
+ pr_info("share pool: no need to unshare uva(to task), "
+ "target process not found or do_exit\n");
+ ret = -EINVAL;
+ rcu_read_unlock();
+ sp_dump_stack();
+ goto out_drop_area;
+ }
+ get_task_struct(tsk);
rcu_read_unlock();
- if (ret)
+
+ if (!spa->mm ||
+ (current->mm && (current->mm != tsk->mm || tsk->mm != spa->mm))) {
+ if (printk_ratelimit())
+ pr_err("share pool: unshare uva(to task) failed, "
+ "wrong pid or invalid spa\n");
+ ret = -EINVAL;
goto out_drop_area;
+ }
+
+ if (spa->mm != tsk->mm) {
+ if (printk_ratelimit())
+ pr_err("share pool: unshare uva(to task) failed, "
+ "spa not belong to the task\n");
+ ret = -EINVAL;
+ goto out_drop_area;
+ }
if (!mmget_not_zero(tsk->mm)) {
put_task_struct(tsk);
- pr_info("share pool: no need to unshare uva, target process is exiting\n");
+ if (printk_ratelimit())
+ pr_info("share pool: no need to unshare uva(to task), "
+ "target process mm is not existing\n");
+ sp_dump_stack();
goto out_drop_area;
}
down_write(&tsk->mm->mmap_sem);
@@ -1809,32 +1901,51 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp
(void *)uva_aligned);
}
put_task_struct(tsk);
- } else {
- /*
- * k2u to task, then unshare_uva(..., spg_id) is invalid due to potential
- * spa memory leak.
- */
- if (!spa->spg) {
+ } else if (spa->type == SPA_TYPE_K2SPG) {
+ if (!spa->spg || spg_id == SPG_ID_NONE) {
+ if (printk_ratelimit())
+ pr_err("share pool: unshare uva(to group) failed, "
+ "invalid spg id %d\n", spg_id);
ret = -EINVAL;
+ goto out_drop_area;
+ }
+
+ spg = __sp_find_spg(pid, SPG_ID_DEFAULT);
+ if (!spg_valid(spg)) {
if (printk_ratelimit())
- pr_err("share pool: unshare uva failed, sp group id %d is invalid\n", spg_id);
+ pr_err("share pool: unshare uva(to group) invalid pid, "
+ "process not in sp group or group is dead\n");
+ ret = -EINVAL;
goto out_drop_area;
}
- spg = __sp_find_spg(pid, spg_id);
- if (spg_valid(spg)) {
- __sp_free(spg, uva_aligned, size_aligned, NULL);
- } else {
- if (!spg) {
- if (printk_ratelimit())
- pr_err("share pool: unshare uva failed, doesn't belong to group %d\n",
- spg_id);
- ret = -EINVAL;
- goto out_drop_area;
- } else {
- pr_info("share pool: no need to unshare uva, target process is exiting\n");
- }
+ if (spa->spg != spg) {
+ if (printk_ratelimit())
+ pr_err("share pool: unshare uva(to group) failed, "
+ "spa not belong to the group\n");
+ ret = -EINVAL;
+ goto out_drop_area;
}
+
+ if (current->mm && current->mm->sp_group != spg) {
+ if (printk_ratelimit())
+ pr_err("share pool: unshare uva(to group) failed, "
+ "caller process doesn't belong to target group\n");
+ ret = -EINVAL;
+ goto out_drop_area;
+ }
+
+ __sp_free(spg, uva_aligned, size_aligned, NULL);
+ }
+
+ if (!ret) {
+ if (spg_valid(spa->spg))
+ spg_id = spa->spg->id;
+ pr_notice("share pool: [sp unshare uva type %d] caller %s(%d/%d); "
+ "group id %d addr 0x%pK size %ld\n",
+ spa->type, current->comm, current->tgid, current->pid,
+ spg_id, (void *)spa->va_start, spa->real_size);
+ sp_dump_stack();
}
out_drop_area:
@@ -1864,7 +1975,8 @@ static int sp_unshare_kva(unsigned long kva, unsigned long size)
step = PAGE_SIZE;
is_hugepage = false;
} else {
- pr_err("share pool: check vmap hugepage failed, ret %d\n", ret);
+ if (printk_ratelimit())
+ pr_err("share pool: check vmap hugepage failed, ret %d\n", ret);
return -EINVAL;
}
@@ -1882,7 +1994,8 @@ static int sp_unshare_kva(unsigned long kva, unsigned long size)
if (page)
put_page(page);
else
- pr_err("share pool: vmalloc to hugepage failed\n");
+ pr_err("share pool: vmalloc %pK to page/hugepage failed\n",
+ (void *)addr);
}
vunmap((void *)kva_aligned);
@@ -1944,7 +2057,7 @@ int sp_walk_page_range(unsigned long uva, unsigned long size,
get_task_struct(tsk);
if (!mmget_not_zero(tsk->mm)) {
put_task_struct(tsk);
- return -EINVAL;
+ return -ESRCH;
}
down_write(&tsk->mm->mmap_sem);
ret = __sp_walk_page_range(uva, size, tsk, sp_walk_data);
@@ -1973,46 +2086,6 @@ void sp_walk_page_free(struct sp_walk_data *sp_walk_data)
}
EXPORT_SYMBOL_GPL(sp_walk_page_free);
-/**
- * Walk the mm_struct of processes in the specified sp_group
- * and call CALLBACK once for each mm_struct.
- * @spg_id: the ID of the specified sp_group
- * @data: the param for callback function
- * @func: caller specific callback function
- *
- * Return -errno if fail.
- */
-int sp_group_walk(int spg_id, void *data, int (*func)(struct mm_struct *mm, void *))
-{
- struct sp_group *spg;
- int ret = -ESRCH;
-
- if (!func) {
- if (printk_ratelimit())
- pr_err("share pool: null func pointer\n");
- return -EINVAL;
- }
-
- mutex_lock(&sp_mutex);
- spg = idr_find(&sp_group_idr, spg_id);
- if (spg_valid(spg)) {
- struct mm_struct *mm;
- struct mm_struct *tmp;
- list_for_each_entry_safe(mm, tmp, &spg->procs, sp_node) {
- if (func) {
- ret = func(mm, data);
- if (ret)
- goto out_unlock;
- }
- }
- }
-out_unlock:
- mutex_unlock(&sp_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(sp_group_walk);
-
int sp_register_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&sp_notifier_chain, nb);
@@ -2039,7 +2112,7 @@ bool sp_config_dvpp_range(size_t start, size_t size, int device_id, int pid)
struct sp_group *spg;
if (device_id < 0 || device_id >= MAX_DEVID || pid < 0 || size <= 0 ||
- size > MMAP_SHARE_POOL_16G_SIZE)
+ size> MMAP_SHARE_POOL_16G_SIZE)
return false;
mutex_lock(&sp_mutex);
@@ -2061,11 +2134,9 @@ EXPORT_SYMBOL_GPL(sp_config_dvpp_range);
/* Check whether the address belongs to the share pool. */
bool is_sharepool_addr(unsigned long addr)
{
- if (host_svm_sp_enable == false)
- return (addr >= MMAP_SHARE_POOL_START) &&
- addr < (MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE);
-
- return addr >= MMAP_SHARE_POOL_START && addr < MMAP_SHARE_POOL_END;
+ if (host_svm_sp_enable == false)
+ return addr >= MMAP_SHARE_POOL_START && addr < (MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE);
+ return addr >= MMAP_SHARE_POOL_START && addr < MMAP_SHARE_POOL_END;
}
EXPORT_SYMBOL_GPL(is_sharepool_addr);
@@ -2109,7 +2180,7 @@ static int idr_proc_stat_cb(int id, void *p, void *data)
mutex_lock(&sp_mutex);
spg = __sp_find_spg(id, SPG_ID_DEFAULT);
- if (spg) {
+ if (spg_valid(spg)) {
seq_printf(seq, "%-12d %-10d %-18ld\n",
id, spg->id, byte2kb(stat->amount));
}
@@ -2130,8 +2201,7 @@ static int proc_stat_show(struct seq_file *seq, void *offset)
return 0;
}
-static void rb_spa_stat_show(struct seq_file *seq)
-{
+static void rb_spa_stat_show(struct seq_file *seq) {
struct rb_node *node;
struct sp_area *spa;
@@ -2215,8 +2285,8 @@ static int idr_spg_stat_cb(int id, void *p, void *data)
struct sp_group *spg = p;
struct seq_file *seq = data;
- seq_printf(seq, "Group %-10d size: %13d KB, spa num: %d.\n",
- id, byte2kb(atomic_read(&spg->size)),
+ seq_printf(seq, "Group %-10d size: %13ld KB, spa num: %d.\n",
+ id, byte2kb(atomic64_read(&spg->size)),
atomic_read(&spg->spa_num));
return 0;
@@ -2227,8 +2297,8 @@ static void spg_overview_show(struct seq_file *seq)
mutex_lock(&sp_mutex);
idr_for_each(&sp_group_idr, idr_spg_stat_cb, seq);
mutex_unlock(&sp_mutex);
- seq_printf(seq, "Share pool total size: %13d KB, spa total num: %d.\n\n",
- byte2kb(atomic_read(&spg_stat.spa_total_size)),
+ seq_printf(seq, "Share pool total size: %13ld KB, spa total num: %d.\n\n",
+ byte2kb(atomic64_read(&spg_stat.spa_total_size)),
atomic_read(&spg_stat.spa_total_num));
}
@@ -2255,7 +2325,6 @@ void __init proc_sharepool_init(void)
proc_create_single_data("sharepool/spa_stat", 0, NULL, spa_stat_show, NULL);
}
-
struct page *sp_alloc_pages(struct vm_struct *area, gfp_t mask,
unsigned int page_order, int node)
{
--
2.25.1
1
1
From: Len Brown <len.brown(a)intel.com>
stable inclusion
from linux-4.19.157
commit 900281e167f45e0c0e5df6e59fa00334b5e38133
CVE: CVE-2020-8694
--------------------------------
commit 949dd0104c496fa7c14991a23c03c62e44637e71 upstream.
Remove non-privileged user access to power data contained in
/sys/class/powercap/intel-rapl*/*/energy_uj
Non-privileged users currently have read access to power data and can
use this data to form a security attack. Some privileged
drivers/applications need read access to this data, but don't expose it
to non-privileged users.
For example, thermald uses this data to ensure that power management
works correctly. Thus removing non-privileged access is preferred over
completely disabling this power reporting capability with
CONFIG_INTEL_RAPL=n.
Fixes: 95677a9a3847 ("PowerCap: Fix mode for energy counter")
Signed-off-by: Len Brown <len.brown(a)intel.com>
Cc: stable(a)vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/powercap/powercap_sys.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
index 9e2f274bd44f..60c8375c3c81 100644
--- a/drivers/powercap/powercap_sys.c
+++ b/drivers/powercap/powercap_sys.c
@@ -379,9 +379,9 @@ static void create_power_zone_common_attributes(
&dev_attr_max_energy_range_uj.attr;
if (power_zone->ops->get_energy_uj) {
if (power_zone->ops->reset_energy_uj)
- dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
+ dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUSR;
else
- dev_attr_energy_uj.attr.mode = S_IRUGO;
+ dev_attr_energy_uj.attr.mode = S_IRUSR;
power_zone->zone_dev_attrs[count++] =
&dev_attr_energy_uj.attr;
}
--
2.25.1
1
0
openEuler Summit 已经得到了
大家的很多支持
演讲议题、支持单位、SIG、Demo 还在增加
但是,申报议题和Demo今天就是 Deadline 了
11月20日23:59截至,
不要错过你发展最迅速、最具活力的首届openEuler Summit 展示自己的技术实力
赶快点击下方的链接报名
申请链接
Call for Speaker<https://shimo.im/forms/XtCTP9jcrXKgjytD/fill>
Call for Sponsor<https://shimo.im/forms/VWWtgLsVHzovmbeH/fill>
Call for SIG<https://shimo.im/forms/KSMKHGPHIAsjoNHP/fill>
Call for Demo<https://shimo.im/forms/lMTsArbYcy4hd2dY/fill>
[cid:image001.png@01D6BF24.25DA26F0]<https://openeuler.org/zh/interaction/summit-list/>
在 openEuler Summit
人人都是主办方
人人都是参与者
这和开源精神的内核是一致的
大会议程日益丰满
并且干货满满、富有趣味
Hello openEuler 开发者体验区
非常的酷
因为我们想到了一个
从树莓派到数据中心的全场景展示
还有其他一些
“别有用心” 的 Demo
绝对的好玩
TC、SIG、Maintainer 已经准备好了
“网友见面”
现场召开 TC 工作会议
现场召开 SIG 组工作会议
现场接受新 SIG 申请
现场的 Maintainer 共同分享学习
不断增加的支持单位、友好基金会和社区媒体
[cid:image001.jpg@01D6BF21.1ADA52F0]
1
0
19 Nov '20
From: Dmitry Torokhov <dmitry.torokhov(a)gmail.com>
mainline inclusion
from mainline-v5.10-rc5
commit 77e70d351db7de07a46ac49b87a6c3c7a60fca7e
category: bugfix
bugzilla: NA
CVE: CVE-2020-25669
--------------------------------
We need to make sure we cancel the reinit work before we tear down the
driver structures.
Reported-by: Bodong Zhao <nopitydays(a)gmail.com>
Tested-by: Bodong Zhao <nopitydays(a)gmail.com>
Cc: stable(a)vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov(a)gmail.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/input/keyboard/sunkbd.c | 41 ++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 8 deletions(-)
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index ad5d7f94f95a..1c7aa86c92ab 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -111,7 +111,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
switch (data) {
case SUNKBD_RET_RESET:
- schedule_work(&sunkbd->tq);
+ if (sunkbd->enabled)
+ schedule_work(&sunkbd->tq);
sunkbd->reset = -1;
break;
@@ -212,16 +213,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
}
/*
- * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
- * were in.
+ * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
+ * they were in.
*/
-static void sunkbd_reinit(struct work_struct *work)
+static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
{
- struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
-
- wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
-
serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
serio_write(sunkbd->serio,
(!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) |
@@ -234,11 +231,39 @@ static void sunkbd_reinit(struct work_struct *work)
SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
}
+
+/*
+ * sunkbd_reinit() wait for the keyboard reset to complete and restores state
+ * of leds and beeps.
+ */
+
+static void sunkbd_reinit(struct work_struct *work)
+{
+ struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
+
+ /*
+ * It is OK that we check sunkbd->enabled without pausing serio,
+ * as we only want to catch true->false transition that will
+ * happen once and we will be woken up for it.
+ */
+ wait_event_interruptible_timeout(sunkbd->wait,
+ sunkbd->reset >= 0 || !sunkbd->enabled,
+ HZ);
+
+ if (sunkbd->reset >= 0 && sunkbd->enabled)
+ sunkbd_set_leds_beeps(sunkbd);
+}
+
static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
{
serio_pause_rx(sunkbd->serio);
sunkbd->enabled = enable;
serio_continue_rx(sunkbd->serio);
+
+ if (!enable) {
+ wake_up_interruptible(&sunkbd->wait);
+ cancel_work_sync(&sunkbd->tq);
+ }
}
/*
--
2.25.1
1
0
19 Nov '20
From: Ming Lei <ming.lei(a)redhat.com>
mainline inclusion
from mainline-v5.10-rc2
commit b40813ddcd6b
category: bugfix
bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1891363
CVE: NA
backport: openEuler-20.09
Here is the testcase:
1. rbd create --size 2G rbdpool/foo
2. rbd-nbd map rbdpool/foo
3. mkfs.ext4 /dev/nbd0
4. mount /dev/nbd0 /mnt
5. rbd resize --size 4G rbdpool/foo
6. ls /mnt
ls will stuck here forever.
--------------------------------
[ Upstream commit b40813ddcd6bf9f01d020804e4cb8febc480b9e4 ]
Mounted NBD device can be resized, one use case is rbd-nbd.
Fix the issue by setting up default block size, then not touch it
in nbd_size_update() any more. This kind of usage is aligned with loop
which has same use case too.
Cc: stable(a)vger.kernel.org
Fixes: c8a83a6b54d0 ("nbd: Use set_blocksize() to set device blocksize")
Reported-by: lining <lining2020x(a)163.com>
Signed-off-by: Ming Lei <ming.lei(a)redhat.com>
Cc: Josef Bacik <josef(a)toxicpanda.com>
Cc: Jan Kara <jack(a)suse.cz>
Tested-by: lining <lining2020x(a)163.com>
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: lining <lining_yewu(a)cmss.chinamobile.com>
---
drivers/block/nbd.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index cdf62fb94fb15..9a0fb2d52a76c 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -268,7 +268,7 @@ static void nbd_size_clear(struct nbd_device *nbd)
}
}
-static void nbd_size_update(struct nbd_device *nbd)
+static void nbd_size_update(struct nbd_device *nbd, bool start)
{
struct nbd_config *config = nbd->config;
struct block_device *bdev = bdget_disk(nbd->disk, 0);
@@ -279,7 +279,8 @@ static void nbd_size_update(struct nbd_device *nbd)
if (bdev) {
if (bdev->bd_disk) {
bd_set_size(bdev, config->bytesize);
- set_blocksize(bdev, config->blksize);
+ if (start)
+ set_blocksize(bdev, config->blksize);
} else
bdev->bd_invalidated = 1;
bdput(bdev);
@@ -294,7 +295,7 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize,
config->blksize = blocksize;
config->bytesize = blocksize * nr_blocks;
if (nbd->task_recv != NULL)
- nbd_size_update(nbd);
+ nbd_size_update(nbd, false);
}
static void nbd_complete_rq(struct request *req)
@@ -1231,7 +1232,7 @@ static int nbd_start_device(struct nbd_device *nbd)
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
- nbd_size_update(nbd);
+ nbd_size_update(nbd, true);
return error;
}
--
2.27.0
3
2
*** BLURB HERE ***
Greg Kroah-Hartman (1):
Linux 4.19.157
Len Brown (1):
powercap: restrict energy meter to root access
Makefile | 2 +-
drivers/powercap/powercap_sys.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
--
2.25.1
1
2
Alan Stern (1):
USB: Add NO_LPM quirk for Kingston flash drive
Alexander Aring (1):
gfs2: Wake up when sd_glock_disposal becomes zero
Artem Lapkin (1):
ALSA: usb-audio: add usb vendor id as DSD-capable for Khadas devices
Ben Hutchings (1):
Revert "btrfs: flush write bio if we loop in extent_write_cache_pages"
Chris Wilson (1):
drm/i915: Break up error capture compression loops with cond_resched()
Claire Chang (1):
serial: 8250_mtk: Fix uart_get_baud_rate warning
Claudiu Manoil (2):
gianfar: Replace skb_realloc_headroom with skb_cow_head for PTP
gianfar: Account for Tx PTP timestamp in the skb headroom
Clément Péron (1):
ARM: dts: sun4i-a10: fix cpu_alert temperature
Daniel Vetter (1):
vt: Disable KD_FONT_OP_COPY
Daniele Palmas (3):
net: usb: qmi_wwan: add Telit LE910Cx 0x1230 composition
USB: serial: option: add LE910Cx compositions 0x1203, 0x1230, 0x1231
USB: serial: option: add Telit FN980 composition 0x1055
Eddy Wu (1):
fork: fix copy_process(CLONE_PARENT) race with the exiting
->real_parent
Filipe Manana (1):
Btrfs: fix unwritten extent buffers and hangs on future writeback
attempts
Gabriel Krisman Bertazi (2):
blk-cgroup: Fix memleak on error path
blk-cgroup: Pre-allocate tree node on blkg_conf_prep
Geoffrey D. Bennett (2):
ALSA: usb-audio: Add implicit feedback quirk for Qu-16
ALSA: usb-audio: Add implicit feedback quirk for MODX
Greg Kroah-Hartman (1):
Linux 4.19.156
Guenter Roeck (1):
tools: perf: Fix build error in v4.19.y
Hoang Huu Le (1):
tipc: fix use-after-free in tipc_bcast_get_mode
Hoegeun Kwon (1):
drm/vc4: drv: Add error handding for bind
Jason Gunthorpe (1):
mm: always have io_remap_pfn_range() set pgprot_decrypted()
Jeff Vander Stoep (1):
vsock: use ns_capable_noaudit() on socket create
Johan Hovold (1):
USB: serial: cyberjack: fix write-URB completion race
Josef Bacik (1):
btrfs: flush write bio if we loop in extent_write_cache_pages
Kairui Song (1):
x86/kexec: Use up-to-dated screen_info copy to fill boot params
Keith Winstein (1):
ALSA: usb-audio: Add implicit feedback quirk for Zoom UAC-2
Lee Jones (1):
Fonts: Replace discarded const qualifier
Macpaul Lin (1):
usb: mtu3: fix panic in mtu3_gadget_stop()
Mark Deneen (1):
cadence: force nonlinear buffers to be cloned
Mike Galbraith (1):
futex: Handle transient "ownerless" rtmutex state correctly
Ming Lei (1):
scsi: core: Don't start concurrent async scan on same host
Oleg Nesterov (1):
ptrace: fix task_join_group_stop() for the case when current is traced
Pali Rohár (1):
arm64: dts: marvell: espressobin: Add ethernet switch aliases
Petr Malat (1):
sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian
platforms
Qinglang Miao (1):
serial: txx9: add missing platform_driver_unregister() on error in
serial_txx9_init
Qiujun Huang (1):
tracing: Fix out of bounds write in get_trace_buf
Qu Wenruo (11):
btrfs: extent_io: Kill the forward declaration of flush_write_bio
btrfs: extent_io: Move the BUG_ON() in flush_write_bio() one level up
btrfs: extent_io: Handle errors better in btree_write_cache_pages()
btrfs: extent_io: add proper error handling to
lock_extent_buffer_for_io()
btrfs: Move btrfs_check_chunk_valid() to tree-check.[ch] and export it
btrfs: tree-checker: Make chunk item checker messages more readable
btrfs: tree-checker: Make btrfs_check_chunk_valid() return EUCLEAN
instead of EIO
btrfs: tree-checker: Check chunk item at tree block read time
btrfs: tree-checker: Verify dev item
btrfs: tree-checker: Fix wrong check on max devid
btrfs: tree-checker: fix the error message for transid error
Rafael J. Wysocki (1):
PM: runtime: Resume the device earlier in __device_release_driver()
Shijie Luo (1):
mm: mempolicy: fix potential pte_unmap_unlock pte error
Steven Rostedt (VMware) (3):
ring-buffer: Fix recursion protection transitions between interrupt
context
ftrace: Fix recursion check for NMI test
ftrace: Handle tracing when switching between context
Vasily Gorbik (1):
lib/crc32test: remove extra local_irq_disable/enable
Vinay Kumar Yadav (2):
chelsio/chtls: fix memory leaks caused by a race
chelsio/chtls: fix always leaking ctrl_skb
Vincent Whitchurch (1):
of: Fix reserved-memory overlap detection
Vineet Gupta (2):
ARC: stack unwinding: avoid indefinite looping
Revert "ARC: entry: fix potential EFA clobber when TIF_SYSCALL_TRACE"
Xiaofei Shen (1):
net: dsa: read mac address from DT for slave device
YueHaibing (1):
sfp: Fix error handing in sfp_probe()
Zhang Qilong (1):
ACPI: NFIT: Fix comparison to '-ENXIO'
Ziyi Cao (1):
USB: serial: option: add Quectel EC200T module support
Zqiang (1):
kthread_worker: prevent queuing delayed work from timer_fn when it is
being canceled
Makefile | 2 +-
arch/arc/kernel/entry.S | 16 +-
arch/arc/kernel/stacktrace.c | 7 +-
arch/arm/boot/dts/sun4i-a10.dtsi | 2 +-
.../dts/marvell/armada-3720-espressobin.dts | 12 +-
arch/x86/kernel/kexec-bzimage64.c | 3 +-
block/blk-cgroup.c | 15 +-
drivers/acpi/nfit/core.c | 2 +-
drivers/base/dd.c | 7 +-
drivers/crypto/chelsio/chtls/chtls_cm.c | 2 +-
drivers/crypto/chelsio/chtls/chtls_hw.c | 3 +
drivers/gpu/drm/i915/i915_gpu_error.c | 3 +
drivers/gpu/drm/vc4/vc4_drv.c | 1 +
drivers/net/ethernet/cadence/macb_main.c | 3 +-
drivers/net/ethernet/freescale/gianfar.c | 14 +-
drivers/net/phy/sfp.c | 3 +-
drivers/net/usb/qmi_wwan.c | 1 +
drivers/of/of_reserved_mem.c | 13 +-
drivers/scsi/scsi_scan.c | 7 +-
drivers/tty/serial/8250/8250_mtk.c | 2 +-
drivers/tty/serial/serial_txx9.c | 3 +
drivers/tty/vt/vt.c | 24 +-
drivers/usb/core/quirks.c | 3 +
drivers/usb/mtu3/mtu3_gadget.c | 1 +
drivers/usb/serial/cyberjack.c | 7 +-
drivers/usb/serial/option.c | 10 +
fs/btrfs/extent_io.c | 171 +++++++++----
fs/btrfs/tree-checker.c | 236 +++++++++++++++++-
fs/btrfs/tree-checker.h | 4 +
fs/btrfs/volumes.c | 123 +--------
fs/btrfs/volumes.h | 9 +
fs/gfs2/glock.c | 3 +-
include/asm-generic/pgtable.h | 4 -
include/linux/mm.h | 9 +
include/net/dsa.h | 1 +
kernel/fork.c | 10 +-
kernel/futex.c | 16 +-
kernel/kthread.c | 3 +-
kernel/signal.c | 19 +-
kernel/trace/ring_buffer.c | 58 ++++-
kernel/trace/trace.c | 2 +-
kernel/trace/trace.h | 26 +-
kernel/trace/trace_selftest.c | 9 +-
lib/crc32test.c | 4 -
lib/fonts/font_10x18.c | 2 +-
lib/fonts/font_6x10.c | 2 +-
lib/fonts/font_6x11.c | 2 +-
lib/fonts/font_7x14.c | 2 +-
lib/fonts/font_8x16.c | 2 +-
lib/fonts/font_8x8.c | 2 +-
lib/fonts/font_acorn_8x8.c | 2 +-
lib/fonts/font_mini_4x6.c | 2 +-
lib/fonts/font_pearl_8x8.c | 2 +-
lib/fonts/font_sun12x22.c | 2 +-
lib/fonts/font_sun8x16.c | 2 +-
mm/mempolicy.c | 6 +-
net/dsa/dsa2.c | 1 +
net/dsa/slave.c | 5 +-
net/sctp/sm_sideeffect.c | 4 +-
net/tipc/core.c | 5 +
net/vmw_vsock/af_vsock.c | 2 +-
sound/usb/pcm.c | 6 +
sound/usb/quirks.c | 1 +
tools/perf/util/util.h | 2 +-
64 files changed, 634 insertions(+), 293 deletions(-)
--
2.25.1
1
66
From: Guenter Roeck <linux(a)roeck-us.net>
perf may fail to build in v4.19.y with the following error.
util/evsel.c: In function ‘perf_evsel__exit’:
util/util.h:25:28: error:
passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type
This is observed (at least) with gcc v6.5.0. The underlying problem is
the following statement.
zfree(&evsel->pmu_name);
evsel->pmu_name is decared 'const *'. zfree in turn is defined as
#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
and thus passes the const * to free(). The problem is not seen
in the upstream kernel since zfree() has been rewritten there.
The problem has been introduced into v4.19.y with the backport of upstream
commit d4953f7ef1a2 (perf parse-events: Fix 3 use after frees found with
clang ASAN).
One possible fix of this problem would be to not declare pmu_name
as const. This patch chooses to typecast the parameter of zfree()
to void *, following the guidance from the upstream kernel which
does the same since commit 7f7c536f23e6a ("tools lib: Adopt
zalloc()/zfree() from tools/perf")
Fixes: a0100a363098 ("perf parse-events: Fix 3 use after frees found with clang ASAN")
Signed-off-by: Guenter Roeck <linux(a)roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
tools/perf/util/util.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index dc58254a2b69..8c01b2cfdb1a 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -22,7 +22,7 @@ static inline void *zalloc(size_t size)
return calloc(1, size);
}
-#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+#define zfree(ptr) ({ free((void *)*ptr); *ptr = NULL; })
struct dirent;
struct nsinfo;
--
2.25.1
1
0
18 Nov '20
From: Israel Rukshin <israelr(a)mellanox.com>
mainline inclusion
from mainline-v5.7-rc1
commit b780d7415aacec855e2f2370cbf98f918b224903
category: bugfix
bugzilla: NA
CVE: NA
Link: https://gitee.com/openeuler/kernel/issues/I1WGZE
--------------------------------
In case nvme_sysfs_delete() is called by the user before taking the ctrl
reference count, the ctrl may be freed during the creation and cause the
bug. Take the reference as soon as the controller is externally visible,
which is done by cdev_device_add() in nvme_init_ctrl(). Also take the
reference count at the core layer instead of taking it on each transport
separately.
Signed-off-by: Israel Rukshin <israelr(a)mellanox.com>
Reviewed-by: Max Gurtovoy <maxg(a)mellanox.com>
Reviewed-by: Christoph Hellwig <hch(a)lst.de>
Signed-off-by: Keith Busch <kbusch(a)kernel.org>
Conflicts:
drivers/nvme/host/tcp.c
[No code about TCP in current version.]
Reviewed-by: Chao Leng <lengchao(a)huawei.com>
Reviewed-by: Jike Cheng <chengjike.cheng(a)huawei.com>
Signed-off-by: Lijie <lijie34(a)huawei.com>
Reviewed-by: Hou Tao <houtao1(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/nvme/host/core.c | 2 ++
drivers/nvme/host/fc.c | 4 +---
drivers/nvme/host/pci.c | 1 -
drivers/nvme/host/rdma.c | 3 +--
drivers/nvme/target/loop.c | 3 +--
5 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index b8446637b3c2..b7a40ac4b637 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3779,6 +3779,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
if (ret)
goto out_release_instance;
+ nvme_get_ctrl(ctrl);
cdev_init(&ctrl->cdev, &nvme_dev_fops);
ctrl->cdev.owner = ops->module;
ret = cdev_device_add(&ctrl->cdev, ctrl->device);
@@ -3795,6 +3796,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
return 0;
out_free_name:
+ nvme_put_ctrl(ctrl);
kfree_const(ctrl->device->kobj.name);
out_release_instance:
ida_simple_remove(&nvme_instance_ida, ctrl->instance);
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index ed88d5021772..d75ae1b201ad 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -3146,10 +3146,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
goto fail_ctrl;
}
- nvme_get_ctrl(&ctrl->ctrl);
-
if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
- nvme_put_ctrl(&ctrl->ctrl);
dev_err(ctrl->ctrl.device,
"NVME-FC{%d}: failed to schedule initial connect\n",
ctrl->cnum);
@@ -3174,6 +3171,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
/* initiate nvme ctrl ref counting teardown */
nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_put_ctrl(&ctrl->ctrl);
/* Remove core ctrl ref. */
nvme_put_ctrl(&ctrl->ctrl);
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index f194bb7ccb04..1a0eec110614 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2558,7 +2558,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
nvme_reset_ctrl(&dev->ctrl);
- nvme_get_ctrl(&dev->ctrl);
async_schedule(nvme_async_probe, dev);
return 0;
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index d0cf19e593b2..0e998e85e962 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -2050,8 +2050,6 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs\n",
ctrl->ctrl.opts->subsysnqn, &ctrl->addr);
- nvme_get_ctrl(&ctrl->ctrl);
-
mutex_lock(&nvme_rdma_ctrl_mutex);
list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list);
mutex_unlock(&nvme_rdma_ctrl_mutex);
@@ -2061,6 +2059,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
out_uninit_ctrl:
nvme_uninit_ctrl(&ctrl->ctrl);
nvme_put_ctrl(&ctrl->ctrl);
+ nvme_put_ctrl(&ctrl->ctrl);
if (ret > 0)
ret = -EIO;
return ERR_PTR(ret);
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index 137a27fa369c..e30080c629fd 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -639,8 +639,6 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
dev_info(ctrl->ctrl.device,
"new ctrl: \"%s\"\n", ctrl->ctrl.opts->subsysnqn);
- nvme_get_ctrl(&ctrl->ctrl);
-
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed);
@@ -658,6 +656,7 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
kfree(ctrl->queues);
out_uninit_ctrl:
nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_put_ctrl(&ctrl->ctrl);
out_put_ctrl:
nvme_put_ctrl(&ctrl->ctrl);
if (ret > 0)
--
2.25.1
1
18
17 Nov '20
mainline inclusion
from mainline-v5.10-rc2
commit b40813ddcd6b
category: bugfix
bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1891363
CVE: NA
backport: openEuler-20.09
Here is the testcase:
1. rbd create --size 2G rbdpool/foo
2. rbd-nbd map rbdpool/foo
3. mkfs.ext4 /dev/nbd0
4. mount /dev/nbd0 /mnt
5. rbd resize --size 4G rbdpool/foo
6. ls /mnt
ls will stuck here forever.
--------------------------------
From: Ming Lei <ming.lei(a)redhat.com>
[ Upstream commit b40813ddcd6bf9f01d020804e4cb8febc480b9e4 ]
Mounted NBD device can be resized, one use case is rbd-nbd.
Fix the issue by setting up default block size, then not touch it
in nbd_size_update() any more. This kind of usage is aligned with loop
which has same use case too.
Cc: stable(a)vger.kernel.org
Fixes: c8a83a6b54d0 ("nbd: Use set_blocksize() to set device blocksize")
Reported-by: lining <lining2020x(a)163.com>
Signed-off-by: Ming Lei <ming.lei(a)redhat.com>
Cc: Josef Bacik <josef(a)toxicpanda.com>
Cc: Jan Kara <jack(a)suse.cz>
Tested-by: lining <lining2020x(a)163.com>
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: lining <lining_yewu(a)cmss.chinamobile.com>
---
drivers/block/nbd.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index cdf62fb94fb15..9a0fb2d52a76c 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -268,7 +268,7 @@ static void nbd_size_clear(struct nbd_device *nbd)
}
}
-static void nbd_size_update(struct nbd_device *nbd)
+static void nbd_size_update(struct nbd_device *nbd, bool start)
{
struct nbd_config *config = nbd->config;
struct block_device *bdev = bdget_disk(nbd->disk, 0);
@@ -279,7 +279,8 @@ static void nbd_size_update(struct nbd_device *nbd)
if (bdev) {
if (bdev->bd_disk) {
bd_set_size(bdev, config->bytesize);
- set_blocksize(bdev, config->blksize);
+ if (start)
+ set_blocksize(bdev, config->blksize);
} else
bdev->bd_invalidated = 1;
bdput(bdev);
@@ -294,7 +295,7 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize,
config->blksize = blocksize;
config->bytesize = blocksize * nr_blocks;
if (nbd->task_recv != NULL)
- nbd_size_update(nbd);
+ nbd_size_update(nbd, false);
}
static void nbd_complete_rq(struct request *req)
@@ -1231,7 +1232,7 @@ static int nbd_start_device(struct nbd_device *nbd)
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
- nbd_size_update(nbd);
+ nbd_size_update(nbd, true);
return error;
}
--
2.27.0
2
1
17 Nov '20
mainline inclusion
from mainline-v5.10-rc2
commit b40813ddcd6b
category: bugfix
bugzilla: 1891363
CVE: NA
--------------------------------
Mounted NBD device can be resized, one use case is rbd-nbd.
Fix the issue by setting up default block size, then not touch it
in nbd_size_update() any more. This kind of usage is aligned with loop
which has same use case too.
Cc: stable(a)vger.kernel.org
Fixes: c8a83a6b54d0 ("nbd: Use set_blocksize() to set device blocksize")
Reported-by: lining <lining2020x(a)163.com>
Signed-off-by: Ming Lei <ming.lei(a)redhat.com>
Cc: Josef Bacik <josef(a)toxicpanda.com>
Cc: Jan Kara <jack(a)suse.cz>
Tested-by: lining <lining2020x(a)163.com>
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
Signed-off-by: lining <lining_yewu(a)cmss.chinamobile.com>
---
drivers/block/nbd.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 816188aa841f..a913153d0b6b 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -293,7 +293,7 @@ static void nbd_size_clear(struct nbd_device *nbd)
}
}
-static void nbd_size_update(struct nbd_device *nbd)
+static void nbd_size_update(struct nbd_device *nbd, bool start)
{
struct nbd_config *config = nbd->config;
struct block_device *bdev = bdget_disk(nbd->disk, 0);
@@ -309,7 +309,8 @@ static void nbd_size_update(struct nbd_device *nbd)
if (bdev) {
if (bdev->bd_disk) {
bd_set_size(bdev, config->bytesize);
- set_blocksize(bdev, config->blksize);
+ if (start)
+ set_blocksize(bdev, config->blksize);
} else
bdev->bd_invalidated = 1;
bdput(bdev);
@@ -324,7 +325,7 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize,
config->blksize = blocksize;
config->bytesize = blocksize * nr_blocks;
if (nbd->task_recv != NULL)
- nbd_size_update(nbd);
+ nbd_size_update(nbd, false);
}
static void nbd_complete_rq(struct request *req)
@@ -1263,7 +1264,7 @@ static int nbd_start_device(struct nbd_device *nbd)
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
- nbd_size_update(nbd);
+ nbd_size_update(nbd, true);
return error;
}
--
2.25.1
2
2
Alexander Duyck (1):
e1000: Do not perform reset in reset_task if we are already down
Alistair Popple (1):
mm/rmap: fixup copying of soft dirty and uffd ptes
Aya Levin (2):
net/mlx5e: Fix VLAN cleanup flow
net/mlx5e: Fix VLAN create flow
Chuck Lever (1):
svcrdma: Fix leak of transport addresses
Cong Wang (1):
tipc: fix the skb_unshare() in tipc_buf_append()
Dan Aloni (1):
svcrdma: fix bounce buffers for unaligned offsets and multiple pages
Dumitru Ceara (1):
openvswitch: handle DNAT tuple collision
Eran Ben Elisha (1):
net/mlx5: Don't call timecounter cyc2time directly from 1PPS flow
Hanjun Guo (4):
irqchip/gicv3: Call acpi_put_table() to fix memory leak
tty/amba-pl011: Call acpi_put_table() to fix memory leak
cpufreq : CPPC: Break out if HiSilicon CPPC workaround is matched
cpufreq: CPPC: put ACPI table after using it
Jonathan Lemon (1):
mlx4: handle non-napi callers to napi_poll
Linus Torvalds (1):
tty: make FONTX ioctl use the tty pointer they were actually passed
Nikolai Merinov (1):
partitions/efi: Fix partition name parsing in GUID partition entry
Rohit Maheshwari (1):
net/tls: sendfile fails with ktls offload
Sabrina Dubroca (1):
xfrmi: drop ignore_df check before updating pmtu
Tonghao Zhang (2):
net: openvswitch: use u64 for meter bucket
net: openvswitch: use div_u64() for 64-by-32 divisions
Tuong Lien (1):
tipc: fix memory leak in service subscripting
Yang Shi (1):
mm: madvise: fix vma user-after-free
Yunsheng Lin (1):
net: sch_generic: aviod concurrent reset and enqueue op for lockless
qdisc
kiyin(尹亮) (1):
perf/core: Fix a memory leak in perf_event_parse_addr_filter()
block/partitions/efi.c | 35 +++++++++----
block/partitions/efi.h | 2 +-
drivers/cpufreq/cppc_cpufreq.c | 8 ++-
drivers/irqchip/irq-gic-v3.c | 2 +
drivers/net/ethernet/intel/e1000/e1000_main.c | 18 +++++--
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 3 ++
drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/en_fs.c | 14 ++++--
.../ethernet/mellanox/mlx5/core/lib/clock.c | 5 +-
drivers/tty/serial/amba-pl011.c | 2 +
drivers/tty/vt/vt_ioctl.c | 32 ++++++------
kernel/events/core.c | 12 ++---
mm/madvise.c | 2 +-
mm/migrate.c | 9 +++-
mm/rmap.c | 7 ++-
net/openvswitch/conntrack.c | 22 +++++----
net/openvswitch/meter.c | 4 +-
net/openvswitch/meter.h | 2 +-
net/sched/sch_generic.c | 49 +++++++++++++------
net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 1 +
net/sunrpc/xprtrdma/svc_rdma_sendto.c | 3 +-
net/tipc/msg.c | 3 +-
net/tipc/topsrv.c | 4 +-
net/tls/tls_device.c | 11 +++--
net/xfrm/xfrm_interface.c | 2 +-
25 files changed, 168 insertions(+), 86 deletions(-)
--
2.25.1
1
24
From: Ding Tianhong <dingtianhong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
The mm->owner is only used for MEMCG currently, but the ascend share
pool features will use it later, so make it to a general features and
select it for CONFIG_MEMCG.
Signed-off-by: Tang Yizhou <tangyizhou(a)huawei.com>
Signed-off-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/mm_types.h | 2 +-
init/Kconfig | 1 +
kernel/exit.c | 4 ++--
kernel/fork.c | 4 ++--
mm/Kconfig | 4 ++++
mm/debug.c | 2 +-
6 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 178e9dee217a..fcfa9a75c18e 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -453,7 +453,7 @@ struct mm_struct {
spinlock_t ioctx_lock;
struct kioctx_table __rcu *ioctx_table;
#endif
-#ifdef CONFIG_MEMCG
+#ifdef CONFIG_MM_OWNER
/*
* "owner" points to a task that is regarded as the canonical
* user/owner of this mm. All of the following must be true in
diff --git a/init/Kconfig b/init/Kconfig
index d1427ae4de9e..6880b55901bb 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -705,6 +705,7 @@ config MEMCG
bool "Memory controller"
select PAGE_COUNTER
select EVENTFD
+ select MM_OWNER
help
Provides control over the memory footprint of tasks in a cgroup.
diff --git a/kernel/exit.c b/kernel/exit.c
index 891d65e3ffd5..4d6f941712b6 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -392,7 +392,7 @@ kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent)
}
}
-#ifdef CONFIG_MEMCG
+#ifdef CONFIG_MM_OWNER
/*
* A task is exiting. If it owned this mm, find a new owner for the mm.
*/
@@ -478,7 +478,7 @@ void mm_update_next_owner(struct mm_struct *mm)
task_unlock(c);
put_task_struct(c);
}
-#endif /* CONFIG_MEMCG */
+#endif /* CONFIG_MM_OWNER */
/*
* Turn us into a lazy TLB process if we
diff --git a/kernel/fork.c b/kernel/fork.c
index 768fe41a7ee3..1ac49d1852cf 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -958,7 +958,7 @@ static void mm_init_aio(struct mm_struct *mm)
static __always_inline void mm_clear_owner(struct mm_struct *mm,
struct task_struct *p)
{
-#ifdef CONFIG_MEMCG
+#ifdef CONFIG_MM_OWNER
if (mm->owner == p)
WRITE_ONCE(mm->owner, NULL);
#endif
@@ -966,7 +966,7 @@ static __always_inline void mm_clear_owner(struct mm_struct *mm,
static void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
{
-#ifdef CONFIG_MEMCG
+#ifdef CONFIG_MM_OWNER
mm->owner = p;
#endif
}
diff --git a/mm/Kconfig b/mm/Kconfig
index dddeb30d645e..76c2197a3f99 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -299,6 +299,10 @@ config VIRT_TO_BUS
deprecated interface virt_to_bus(). All new architectures
should probably not select this.
+config MM_OWNER
+ bool "Enable the ownership the mm owner"
+ help
+ This option enables mm_struct's to have an owner.
config MMU_NOTIFIER
bool
diff --git a/mm/debug.c b/mm/debug.c
index 362ce581671e..2da184b16bce 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -129,7 +129,7 @@ void dump_mm(const struct mm_struct *mm)
#ifdef CONFIG_AIO
"ioctx_table %px\n"
#endif
-#ifdef CONFIG_MEMCG
+#ifdef CONFIG_MM_OWNER
"owner %px "
#endif
"exe_file %px\n"
--
2.25.1
1
9
From: Chenguangli <chenguangli2(a)huawei.com>
driver inclusion
category: feature
bugzilla: NA
-----------------------------------------------------------------------
This module includes cfg, cqm, hwdev, hwif, mgmt, sml. and are mainly used to
initialize chip capabilityes and to initialize resources for communication between
drivers and chip.
Signed-off-by: Chenguangli <chenguangli2(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/huawei/hifc/hifc_api_cmd.c | 1155 ++++++
drivers/scsi/huawei/hifc/hifc_api_cmd.h | 268 ++
drivers/scsi/huawei/hifc/hifc_cfg.c | 823 +++++
drivers/scsi/huawei/hifc/hifc_cfg.h | 171 +
drivers/scsi/huawei/hifc/hifc_cmdq.c | 1507 ++++++++
drivers/scsi/huawei/hifc/hifc_cmdq.h | 210 ++
drivers/scsi/huawei/hifc/hifc_cqm_main.c | 694 ++++
drivers/scsi/huawei/hifc/hifc_cqm_main.h | 366 ++
drivers/scsi/huawei/hifc/hifc_cqm_object.c | 3599 +++++++++++++++++++
drivers/scsi/huawei/hifc/hifc_cqm_object.h | 244 ++
drivers/scsi/huawei/hifc/hifc_eqs.c | 1347 +++++++
drivers/scsi/huawei/hifc/hifc_eqs.h | 233 ++
drivers/scsi/huawei/hifc/hifc_hw.h | 611 ++++
drivers/scsi/huawei/hifc/hifc_hwdev.c | 3675 ++++++++++++++++++++
drivers/scsi/huawei/hifc/hifc_hwdev.h | 456 +++
drivers/scsi/huawei/hifc/hifc_hwif.c | 630 ++++
drivers/scsi/huawei/hifc/hifc_hwif.h | 243 ++
drivers/scsi/huawei/hifc/hifc_mgmt.c | 1426 ++++++++
drivers/scsi/huawei/hifc/hifc_mgmt.h | 407 +++
drivers/scsi/huawei/hifc/hifc_sml.c | 361 ++
drivers/scsi/huawei/hifc/hifc_sml.h | 183 +
drivers/scsi/huawei/hifc/hifc_wq.c | 624 ++++
drivers/scsi/huawei/hifc/hifc_wq.h | 165 +
23 files changed, 19398 insertions(+)
create mode 100644 drivers/scsi/huawei/hifc/hifc_api_cmd.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_api_cmd.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_cfg.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_cfg.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_cmdq.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_cmdq.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_cqm_main.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_cqm_main.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_cqm_object.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_cqm_object.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_eqs.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_eqs.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_hw.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_hwdev.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_hwdev.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_hwif.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_hwif.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_mgmt.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_mgmt.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_sml.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_sml.h
create mode 100644 drivers/scsi/huawei/hifc/hifc_wq.c
create mode 100644 drivers/scsi/huawei/hifc/hifc_wq.h
diff --git a/drivers/scsi/huawei/hifc/hifc_api_cmd.c b/drivers/scsi/huawei/hifc/hifc_api_cmd.c
new file mode 100644
index 000000000000..22632f779582
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_api_cmd.c
@@ -0,0 +1,1155 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/semaphore.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+
+#define API_CMD_CHAIN_CELL_SIZE_SHIFT 6U
+
+#define API_CMD_CELL_DESC_SIZE 8
+#define API_CMD_CELL_DATA_ADDR_SIZE 8
+
+#define API_CHAIN_NUM_CELLS 32
+#define API_CHAIN_CELL_SIZE 128
+#define API_CHAIN_RSP_DATA_SIZE 128
+
+#define API_CMD_CELL_WB_ADDR_SIZE 8
+
+#define API_CHAIN_CELL_ALIGNMENT 8
+
+#define API_CMD_TIMEOUT 10000
+#define API_CMD_STATUS_TIMEOUT 100000
+
+#define API_CMD_BUF_SIZE 2048ULL
+
+#define API_CMD_NODE_ALIGN_SIZE 512ULL
+#define API_PAYLOAD_ALIGN_SIZE 64ULL
+
+#define API_CHAIN_RESP_ALIGNMENT 64ULL
+
+#define COMPLETION_TIMEOUT_DEFAULT 1000UL
+#define POLLING_COMPLETION_TIMEOUT_DEFAULT 1000U
+
+#define API_CMD_RESPONSE_DATA_PADDR(val) be64_to_cpu(*((u64 *)(val)))
+
+#define READ_API_CMD_PRIV_DATA(id, token) (((id) << 16) + (token))
+#define WRITE_API_CMD_PRIV_DATA(id) (((u8)id) << 16)
+
+#define MASKED_IDX(chain, idx) ((idx) & ((chain)->num_cells - 1))
+
+#define SIZE_4BYTES(size) (ALIGN((u32)(size), 4U) >> 2)
+#define SIZE_8BYTES(size) (ALIGN((u32)(size), 8U) >> 3)
+
+enum api_cmd_data_format {
+ SGL_DATA = 1,
+};
+
+enum api_cmd_type {
+ API_CMD_WRITE_TYPE = 0,
+ API_CMD_READ_TYPE = 1,
+};
+
+enum api_cmd_bypass {
+ NOT_BYPASS = 0,
+ BYPASS = 1,
+};
+
+enum api_cmd_resp_aeq {
+ NOT_TRIGGER = 0,
+ TRIGGER = 1,
+};
+
+static u8 xor_chksum_set(void *data)
+{
+ int idx;
+ u8 checksum = 0;
+ u8 *val = data;
+
+ for (idx = 0; idx < 7; idx++)
+ checksum ^= val[idx];
+
+ return checksum;
+}
+
+static void set_prod_idx(struct hifc_api_cmd_chain *chain)
+{
+ enum hifc_api_cmd_chain_type chain_type = chain->chain_type;
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 hw_prod_idx_addr = HIFC_CSR_API_CMD_CHAIN_PI_ADDR(chain_type);
+ u32 prod_idx = chain->prod_idx;
+
+ hifc_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx);
+}
+
+static u32 get_hw_cons_idx(struct hifc_api_cmd_chain *chain)
+{
+ u32 addr, val;
+
+ addr = HIFC_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type);
+ val = hifc_hwif_read_reg(chain->hwdev->hwif, addr);
+
+ return HIFC_API_CMD_STATUS_GET(val, CONS_IDX);
+}
+
+static void dump_api_chain_reg(struct hifc_api_cmd_chain *chain)
+{
+ void *dev = chain->hwdev->dev_hdl;
+ u32 addr, val;
+
+ addr = HIFC_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type);
+ val = hifc_hwif_read_reg(chain->hwdev->hwif, addr);
+
+ sdk_err(dev, "Chain type: 0x%x, cpld error: 0x%x, check error: 0x%x, current fsm: 0x%x\n",
+ chain->chain_type, HIFC_API_CMD_STATUS_GET(val, CPLD_ERR),
+ HIFC_API_CMD_STATUS_GET(val, CHKSUM_ERR),
+ HIFC_API_CMD_STATUS_GET(val, FSM));
+
+ sdk_err(dev, "Chain hw current ci: 0x%x\n",
+ HIFC_API_CMD_STATUS_GET(val, CONS_IDX));
+
+ addr = HIFC_CSR_API_CMD_CHAIN_PI_ADDR(chain->chain_type);
+ val = hifc_hwif_read_reg(chain->hwdev->hwif, addr);
+ sdk_err(dev, "Chain hw current pi: 0x%x\n", val);
+}
+
+/**
+ * chain_busy - check if the chain is still processing last requests
+ * @chain: chain to check
+ * Return: 0 - success, negative - failure
+ **/
+static int chain_busy(struct hifc_api_cmd_chain *chain)
+{
+ void *dev = chain->hwdev->dev_hdl;
+ struct hifc_api_cmd_cell_ctxt *ctxt;
+ u64 resp_header;
+
+ ctxt = &chain->cell_ctxt[chain->prod_idx];
+
+ switch (chain->chain_type) {
+ case HIFC_API_CMD_MULTI_READ:
+ case HIFC_API_CMD_POLL_READ:
+ resp_header = be64_to_cpu(ctxt->resp->header);
+ if (ctxt->status &&
+ !HIFC_API_CMD_RESP_HEADER_VALID(resp_header)) {
+ sdk_err(dev, "Context(0x%x) busy!, pi: %d, resp_header: 0x%08x%08x\n",
+ ctxt->status, chain->prod_idx,
+ upper_32_bits(resp_header),
+ lower_32_bits(resp_header));
+ dump_api_chain_reg(chain);
+ return -EBUSY;
+ }
+ break;
+ case HIFC_API_CMD_POLL_WRITE:
+ case HIFC_API_CMD_WRITE_TO_MGMT_CPU:
+ case HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:
+ chain->cons_idx = get_hw_cons_idx(chain);
+
+ if (chain->cons_idx == MASKED_IDX(chain, chain->prod_idx + 1)) {
+ sdk_err(dev, "API CMD chain %d is busy, cons_idx = %d, prod_idx = %d\n",
+ chain->chain_type, chain->cons_idx,
+ chain->prod_idx);
+ dump_api_chain_reg(chain);
+ return -EBUSY;
+ }
+ break;
+ default:
+ sdk_err(dev, "Unknown Chain type %d\n", chain->chain_type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * get_cell_data_size - get the data size of specific cell type
+ * @type: chain type
+ * @cmd_size: the command size
+ * Return: cell_data_size
+ **/
+static u16 get_cell_data_size(enum hifc_api_cmd_chain_type type, u16 cmd_size)
+{
+ u16 cell_data_size = 0;
+
+ switch (type) {
+ case HIFC_API_CMD_POLL_READ:
+ cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE +
+ API_CMD_CELL_WB_ADDR_SIZE +
+ API_CMD_CELL_DATA_ADDR_SIZE,
+ API_CHAIN_CELL_ALIGNMENT);
+ break;
+
+ case HIFC_API_CMD_WRITE_TO_MGMT_CPU:
+ case HIFC_API_CMD_POLL_WRITE:
+ case HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:
+ cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE +
+ API_CMD_CELL_DATA_ADDR_SIZE,
+ API_CHAIN_CELL_ALIGNMENT);
+ break;
+ default:
+ break;
+ }
+
+ return cell_data_size;
+}
+
+/**
+ * prepare_cell_ctrl - prepare the ctrl of the cell for the command
+ * @cell_ctrl: the control of the cell to set the control into it
+ * @cell_len: the size of the cell
+ **/
+static void prepare_cell_ctrl(u64 *cell_ctrl, u16 cell_len)
+{
+ u64 ctrl;
+ u8 chksum;
+
+ ctrl = HIFC_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(cell_len), CELL_LEN) |
+ HIFC_API_CMD_CELL_CTRL_SET(0ULL, RD_DMA_ATTR_OFF) |
+ HIFC_API_CMD_CELL_CTRL_SET(0ULL, WR_DMA_ATTR_OFF);
+
+ chksum = xor_chksum_set(&ctrl);
+
+ ctrl |= HIFC_API_CMD_CELL_CTRL_SET(chksum, XOR_CHKSUM);
+
+ /* The data in the HW should be in Big Endian Format */
+ *cell_ctrl = cpu_to_be64(ctrl);
+}
+
+/**
+ * prepare_api_cmd - prepare API CMD command
+ * @chain: chain for the command
+ * @cell: the cell of the command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @cmd_size: the command size
+ **/
+static void prepare_api_cmd(struct hifc_api_cmd_chain *chain,
+ struct hifc_api_cmd_cell *cell,
+ enum hifc_node_id dest,
+ const void *cmd, u16 cmd_size)
+{
+ struct hifc_api_cmd_cell_ctxt *cell_ctxt;
+ u32 priv;
+
+ cell_ctxt = &chain->cell_ctxt[chain->prod_idx];
+
+ switch (chain->chain_type) {
+ case HIFC_API_CMD_POLL_READ:
+ priv = READ_API_CMD_PRIV_DATA(chain->chain_type,
+ cell_ctxt->saved_prod_idx);
+ cell->desc = HIFC_API_CMD_DESC_SET(SGL_DATA, API_TYPE) |
+ HIFC_API_CMD_DESC_SET(API_CMD_READ_TYPE, RD_WR) |
+ HIFC_API_CMD_DESC_SET(BYPASS, MGMT_BYPASS) |
+ HIFC_API_CMD_DESC_SET(NOT_TRIGGER, RESP_AEQE_EN) |
+ HIFC_API_CMD_DESC_SET(priv, PRIV_DATA);
+ break;
+ case HIFC_API_CMD_POLL_WRITE:
+ priv = WRITE_API_CMD_PRIV_DATA(chain->chain_type);
+ cell->desc = HIFC_API_CMD_DESC_SET(SGL_DATA, API_TYPE) |
+ HIFC_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) |
+ HIFC_API_CMD_DESC_SET(BYPASS, MGMT_BYPASS) |
+ HIFC_API_CMD_DESC_SET(NOT_TRIGGER, RESP_AEQE_EN) |
+ HIFC_API_CMD_DESC_SET(priv, PRIV_DATA);
+ break;
+ case HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:
+ case HIFC_API_CMD_WRITE_TO_MGMT_CPU:
+ priv = WRITE_API_CMD_PRIV_DATA(chain->chain_type);
+ cell->desc = HIFC_API_CMD_DESC_SET(SGL_DATA, API_TYPE) |
+ HIFC_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) |
+ HIFC_API_CMD_DESC_SET(NOT_BYPASS, MGMT_BYPASS) |
+ HIFC_API_CMD_DESC_SET(TRIGGER, RESP_AEQE_EN) |
+ HIFC_API_CMD_DESC_SET(priv, PRIV_DATA);
+ break;
+ default:
+ sdk_err(chain->hwdev->dev_hdl, "Unknown Chain type: %d\n",
+ chain->chain_type);
+ return;
+ }
+
+ cell->desc |= HIFC_API_CMD_DESC_SET(dest, DEST) |
+ HIFC_API_CMD_DESC_SET(SIZE_4BYTES(cmd_size), SIZE);
+
+ cell->desc |= HIFC_API_CMD_DESC_SET(xor_chksum_set(&cell->desc),
+ XOR_CHKSUM);
+
+ /* The data in the HW should be in Big Endian Format */
+ cell->desc = cpu_to_be64(cell->desc);
+
+ memcpy(cell_ctxt->api_cmd_vaddr, cmd, cmd_size);
+}
+
+/**
+ * prepare_cell - prepare cell ctrl and cmd in the current producer cell
+ * @chain: chain for the command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @cmd_size: the command size
+ **/
+static void prepare_cell(struct hifc_api_cmd_chain *chain,
+ enum hifc_node_id dest,
+ void *cmd, u16 cmd_size)
+{
+ struct hifc_api_cmd_cell *curr_node;
+ u16 cell_size;
+
+ curr_node = chain->curr_node;
+
+ cell_size = get_cell_data_size(chain->chain_type, cmd_size);
+
+ prepare_cell_ctrl(&curr_node->ctrl, cell_size);
+ prepare_api_cmd(chain, curr_node, dest, cmd, cmd_size);
+}
+
+static inline void cmd_chain_prod_idx_inc(struct hifc_api_cmd_chain *chain)
+{
+ chain->prod_idx = MASKED_IDX(chain, chain->prod_idx + 1);
+}
+
+static void issue_api_cmd(struct hifc_api_cmd_chain *chain)
+{
+ set_prod_idx(chain);
+}
+
+/**
+ * api_cmd_status_update - update the status of the chain
+ * @chain: chain to update
+ **/
+static void api_cmd_status_update(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_api_cmd_status *wb_status;
+ enum hifc_api_cmd_chain_type chain_type;
+ u64 status_header;
+ u32 buf_desc;
+
+ wb_status = chain->wb_status;
+
+ buf_desc = be32_to_cpu(wb_status->buf_desc);
+ if (HIFC_API_CMD_STATUS_GET(buf_desc, CHKSUM_ERR))
+ return;
+
+ status_header = be64_to_cpu(wb_status->header);
+ chain_type = HIFC_API_CMD_STATUS_HEADER_GET(status_header, CHAIN_ID);
+ if (chain_type >= HIFC_API_CMD_MAX)
+ return;
+
+ if (chain_type != chain->chain_type)
+ return;
+
+ chain->cons_idx = HIFC_API_CMD_STATUS_GET(buf_desc, CONS_IDX);
+}
+
+/**
+ * wait_for_status_poll - wait for write to mgmt command to complete
+ * @chain: the chain of the command
+ * Return: 0 - success, negative - failure
+ **/
+static int wait_for_status_poll(struct hifc_api_cmd_chain *chain)
+{
+ int err = -ETIMEDOUT;
+ u32 cnt = 0;
+
+ while (cnt < API_CMD_STATUS_TIMEOUT &&
+ chain->hwdev->chip_present_flag) {
+ api_cmd_status_update(chain);
+
+ /* SYNC API CMD cmd should start after prev cmd finished */
+ if (chain->cons_idx == chain->prod_idx) {
+ err = 0;
+ break;
+ }
+
+ usleep_range(50, 100);
+ cnt++;
+ }
+
+ return err;
+}
+
+static void copy_resp_data(struct hifc_api_cmd_cell_ctxt *ctxt, void *ack,
+ u16 ack_size)
+{
+ struct hifc_api_cmd_resp_fmt *resp = ctxt->resp;
+
+ memcpy(ack, &resp->resp_data, ack_size);
+ ctxt->status = 0;
+}
+
+/**
+ * prepare_cell - polling for respense data of the read api-command
+ * @chain: pointer to api cmd chain
+ *
+ * Return: 0 - success, negative - failure
+ **/
+static int wait_for_resp_polling(struct hifc_api_cmd_cell_ctxt *ctxt)
+{
+ u64 resp_header;
+ int ret = -ETIMEDOUT;
+ u32 cnt = 0;
+
+ while (cnt < POLLING_COMPLETION_TIMEOUT_DEFAULT) {
+ resp_header = be64_to_cpu(ctxt->resp->header);
+
+ rmb(); /* read the latest header */
+
+ if (HIFC_API_CMD_RESP_HEADER_VALID(resp_header)) {
+ ret = 0;
+ break;
+ }
+ usleep_range(100, 1000);
+ cnt++;
+ }
+
+ if (ret)
+ pr_err("Wait for api chain response timeout\n");
+
+ return ret;
+}
+
+/**
+ * wait_for_api_cmd_completion - wait for command to complete
+ * @chain: chain for the command
+ * Return: 0 - success, negative - failure
+ **/
+static int wait_for_api_cmd_completion(struct hifc_api_cmd_chain *chain,
+ struct hifc_api_cmd_cell_ctxt *ctxt,
+ void *ack, u16 ack_size)
+{
+ void *dev = chain->hwdev->dev_hdl;
+ int err = 0;
+
+ switch (chain->chain_type) {
+ case HIFC_API_CMD_POLL_READ:
+ err = wait_for_resp_polling(ctxt);
+ if (!err)
+ copy_resp_data(ctxt, ack, ack_size);
+ break;
+ case HIFC_API_CMD_POLL_WRITE:
+ case HIFC_API_CMD_WRITE_TO_MGMT_CPU:
+ err = wait_for_status_poll(chain);
+ if (err) {
+ sdk_err(dev, "API CMD Poll status timeout, chain type: %d\n",
+ chain->chain_type);
+ break;
+ }
+ break;
+ case HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:
+ /* No need to wait */
+ break;
+ default:
+ sdk_err(dev, "Unknown API CMD Chain type: %d\n",
+ chain->chain_type);
+ err = -EINVAL;
+ break;
+ }
+
+ if (err)
+ dump_api_chain_reg(chain);
+
+ return err;
+}
+
+static inline void update_api_cmd_ctxt(struct hifc_api_cmd_chain *chain,
+ struct hifc_api_cmd_cell_ctxt *ctxt)
+{
+ ctxt->status = 1;
+ ctxt->saved_prod_idx = chain->prod_idx;
+ if (ctxt->resp) {
+ ctxt->resp->header = 0;
+
+ /* make sure "header" was cleared */
+ wmb();
+ }
+}
+
+/**
+ * api_cmd - API CMD command
+ * @chain: chain for the command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @size: the command size
+ * Return: 0 - success, negative - failure
+ **/
+static int api_cmd(struct hifc_api_cmd_chain *chain,
+ enum hifc_node_id dest,
+ void *cmd, u16 cmd_size, void *ack, u16 ack_size)
+{
+ struct hifc_api_cmd_cell_ctxt *ctxt;
+
+ if (chain->chain_type == HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU)
+ spin_lock(&chain->async_lock);
+ else
+ down(&chain->sem);
+ ctxt = &chain->cell_ctxt[chain->prod_idx];
+ if (chain_busy(chain)) {
+ if (chain->chain_type == HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU)
+ spin_unlock(&chain->async_lock);
+ else
+ up(&chain->sem);
+ return -EBUSY;
+ }
+ update_api_cmd_ctxt(chain, ctxt);
+
+ prepare_cell(chain, dest, cmd, cmd_size);
+
+ cmd_chain_prod_idx_inc(chain);
+
+ wmb(); /* issue the command */
+
+ issue_api_cmd(chain);
+
+ /* incremented prod idx, update ctxt */
+
+ chain->curr_node = chain->cell_ctxt[chain->prod_idx].cell_vaddr;
+ if (chain->chain_type == HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU)
+ spin_unlock(&chain->async_lock);
+ else
+ up(&chain->sem);
+
+ return wait_for_api_cmd_completion(chain, ctxt, ack, ack_size);
+}
+
+/**
+ * hifc_api_cmd_write - Write API CMD command
+ * @chain: chain for write command
+ * @dest: destination node on the card that will receive the command
+ * @cmd: command data
+ * @size: the command size
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_api_cmd_write(struct hifc_api_cmd_chain *chain,
+ enum hifc_node_id dest, void *cmd, u16 size)
+{
+ /* Verify the chain type */
+ return api_cmd(chain, dest, cmd, size, NULL, 0);
+}
+
+int hifc_api_cmd_read(struct hifc_api_cmd_chain *chain,
+ enum hifc_node_id dest,
+ void *cmd, u16 size, void *ack, u16 ack_size)
+{
+ return api_cmd(chain, dest, cmd, size, ack, ack_size);
+}
+
+/**
+ * api_cmd_hw_restart - restart the chain in the HW
+ * @chain: the API CMD specific chain to restart
+ **/
+static int api_cmd_hw_restart(struct hifc_api_cmd_chain *cmd_chain)
+{
+ struct hifc_hwif *hwif = cmd_chain->hwdev->hwif;
+ u32 reg_addr, val;
+ int err;
+ u32 cnt = 0;
+
+ /* Read Modify Write */
+ reg_addr = HIFC_CSR_API_CMD_CHAIN_REQ_ADDR(cmd_chain->chain_type);
+ val = hifc_hwif_read_reg(hwif, reg_addr);
+
+ val = HIFC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART);
+ val |= HIFC_API_CMD_CHAIN_REQ_SET(1, RESTART);
+
+ hifc_hwif_write_reg(hwif, reg_addr, val);
+
+ err = -ETIMEDOUT;
+ while (cnt < API_CMD_TIMEOUT) {
+ val = hifc_hwif_read_reg(hwif, reg_addr);
+
+ if (!HIFC_API_CMD_CHAIN_REQ_GET(val, RESTART)) {
+ err = 0;
+ break;
+ }
+
+ usleep_range(900, 1000);
+ cnt++;
+ }
+
+ return err;
+}
+
+/**
+ * api_cmd_ctrl_init - set the control register of a chain
+ * @chain: the API CMD specific chain to set control register for
+ **/
+static void api_cmd_ctrl_init(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 reg_addr, ctrl;
+ u32 size;
+
+ /* Read Modify Write */
+ reg_addr = HIFC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);
+
+ size = (u32)ilog2(chain->cell_size >> API_CMD_CHAIN_CELL_SIZE_SHIFT);
+
+ ctrl = hifc_hwif_read_reg(hwif, reg_addr);
+
+ ctrl = HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) &
+ HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);
+
+ ctrl |= HIFC_API_CMD_CHAIN_CTRL_SET(0, AEQE_EN) |
+ HIFC_API_CMD_CHAIN_CTRL_SET(size, CELL_SIZE);
+
+ hifc_hwif_write_reg(hwif, reg_addr, ctrl);
+}
+
+/**
+ * api_cmd_set_status_addr - set the status address of a chain in the HW
+ * @chain: the API CMD specific chain to set status address for
+ **/
+static void api_cmd_set_status_addr(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 addr, val;
+
+ addr = HIFC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type);
+ val = upper_32_bits(chain->wb_status_paddr);
+ hifc_hwif_write_reg(hwif, addr, val);
+
+ addr = HIFC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type);
+ val = lower_32_bits(chain->wb_status_paddr);
+ hifc_hwif_write_reg(hwif, addr, val);
+}
+
+/**
+ * api_cmd_set_num_cells - set the number cells of a chain in the HW
+ * @chain: the API CMD specific chain to set the number of cells for
+ **/
+static void api_cmd_set_num_cells(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 addr, val;
+
+ addr = HIFC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type);
+ val = chain->num_cells;
+ hifc_hwif_write_reg(hwif, addr, val);
+}
+
+/**
+ * api_cmd_head_init - set the head cell of a chain in the HW
+ * @chain: the API CMD specific chain to set the head for
+ **/
+static void api_cmd_head_init(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 addr, val;
+
+ addr = HIFC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type);
+ val = upper_32_bits(chain->head_cell_paddr);
+ hifc_hwif_write_reg(hwif, addr, val);
+
+ addr = HIFC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type);
+ val = lower_32_bits(chain->head_cell_paddr);
+ hifc_hwif_write_reg(hwif, addr, val);
+}
+
+/**
+ * wait_for_ready_chain - wait for the chain to be ready
+ * @chain: the API CMD specific chain to wait for
+ * Return: 0 - success, negative - failure
+ **/
+static int wait_for_ready_chain(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 addr, val;
+ u32 hw_cons_idx;
+ u32 cnt = 0;
+ int err;
+
+ addr = HIFC_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type);
+ err = -ETIMEDOUT;
+ while (cnt < API_CMD_TIMEOUT) {
+ val = hifc_hwif_read_reg(hwif, addr);
+ hw_cons_idx = HIFC_API_CMD_STATUS_GET(val, CONS_IDX);
+
+ /* wait for HW cons idx to be updated */
+ if (hw_cons_idx == chain->cons_idx) {
+ err = 0;
+ break;
+ }
+
+ usleep_range(900, 1000);
+ cnt++;
+ }
+
+ return err;
+}
+
+/**
+ * api_cmd_chain_hw_clean - clean the HW
+ * @chain: the API CMD specific chain
+ **/
+static void api_cmd_chain_hw_clean(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_hwif *hwif = chain->hwdev->hwif;
+ u32 addr, ctrl;
+
+ addr = HIFC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);
+
+ ctrl = hifc_hwif_read_reg(hwif, addr);
+ ctrl = HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_EN) &
+ HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) &
+ HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) &
+ HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) &
+ HIFC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);
+
+ hifc_hwif_write_reg(hwif, addr, ctrl);
+}
+
+/**
+ * api_cmd_chain_hw_init - initialize the chain in the HW
+ * @chain: the API CMD specific chain to initialize in HW
+ * Return: 0 - success, negative - failure
+ **/
+static int api_cmd_chain_hw_init(struct hifc_api_cmd_chain *chain)
+{
+ api_cmd_chain_hw_clean(chain);
+
+ api_cmd_set_status_addr(chain);
+
+ if (api_cmd_hw_restart(chain)) {
+ sdk_err(chain->hwdev->dev_hdl, "Failed to restart api_cmd_hw\n");
+ return -EBUSY;
+ }
+
+ api_cmd_ctrl_init(chain);
+ api_cmd_set_num_cells(chain);
+ api_cmd_head_init(chain);
+
+ return wait_for_ready_chain(chain);
+}
+
+/**
+ * alloc_cmd_buf - allocate a dma buffer for API CMD command
+ * @chain: the API CMD specific chain for the cmd
+ * @cell: the cell in the HW for the cmd
+ * @cell_idx: the index of the cell
+ * Return: 0 - success, negative - failure
+ **/
+static int alloc_cmd_buf(struct hifc_api_cmd_chain *chain,
+ struct hifc_api_cmd_cell *cell, u32 cell_idx)
+{
+ struct hifc_api_cmd_cell_ctxt *cell_ctxt;
+ void *dev = chain->hwdev->dev_hdl;
+ void *buf_vaddr;
+ u64 buf_paddr;
+ int err = 0;
+
+ buf_vaddr = (u8 *)((u64)chain->buf_vaddr_base +
+ chain->buf_size_align * cell_idx);
+ buf_paddr = chain->buf_paddr_base +
+ chain->buf_size_align * cell_idx;
+
+ cell_ctxt = &chain->cell_ctxt[cell_idx];
+
+ cell_ctxt->api_cmd_vaddr = buf_vaddr;
+
+ /* set the cmd DMA address in the cell */
+ switch (chain->chain_type) {
+ case HIFC_API_CMD_POLL_READ:
+ cell->read.hw_cmd_paddr = cpu_to_be64(buf_paddr);
+ break;
+ case HIFC_API_CMD_WRITE_TO_MGMT_CPU:
+ case HIFC_API_CMD_POLL_WRITE:
+ case HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:
+ /* The data in the HW should be in Big Endian Format */
+ cell->write.hw_cmd_paddr = cpu_to_be64(buf_paddr);
+ break;
+ default:
+ sdk_err(dev, "Unknown API CMD Chain type: %d\n",
+ chain->chain_type);
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static void alloc_resp_buf(struct hifc_api_cmd_chain *chain,
+ struct hifc_api_cmd_cell *cell, u32 cell_idx)
+{
+ struct hifc_api_cmd_cell_ctxt *cell_ctxt;
+ void *resp_vaddr;
+ u64 resp_paddr;
+
+ resp_vaddr = (u8 *)((u64)chain->rsp_vaddr_base +
+ chain->rsp_size_align * cell_idx);
+ resp_paddr = chain->rsp_paddr_base +
+ chain->rsp_size_align * cell_idx;
+
+ cell_ctxt = &chain->cell_ctxt[cell_idx];
+
+ cell_ctxt->resp = resp_vaddr;
+ cell->read.hw_wb_resp_paddr = cpu_to_be64(resp_paddr);
+}
+
+static int hifc_alloc_api_cmd_cell_buf(struct hifc_api_cmd_chain *chain,
+ u32 cell_idx,
+ struct hifc_api_cmd_cell *node)
+{
+ void *dev = chain->hwdev->dev_hdl;
+ int err;
+
+ /* For read chain, we should allocate buffer for the response data */
+ if (chain->chain_type == HIFC_API_CMD_MULTI_READ ||
+ chain->chain_type == HIFC_API_CMD_POLL_READ)
+ alloc_resp_buf(chain, node, cell_idx);
+
+ switch (chain->chain_type) {
+ case HIFC_API_CMD_WRITE_TO_MGMT_CPU:
+ case HIFC_API_CMD_POLL_WRITE:
+ case HIFC_API_CMD_POLL_READ:
+ case HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:
+ err = alloc_cmd_buf(chain, node, cell_idx);
+ if (err) {
+ sdk_err(dev, "Failed to allocate cmd buffer\n");
+ goto alloc_cmd_buf_err;
+ }
+ break;
+ /* For api command write and api command read, the data section
+ * is directly inserted in the cell, so no need to allocate.
+ */
+ case HIFC_API_CMD_MULTI_READ:
+ chain->cell_ctxt[cell_idx].api_cmd_vaddr =
+ &node->read.hw_cmd_paddr;
+ break;
+ default:
+ sdk_err(dev, "Unsupported API CMD chain type\n");
+ err = -EINVAL;
+ goto alloc_cmd_buf_err;
+ }
+
+ return 0;
+
+alloc_cmd_buf_err:
+
+ return err;
+}
+
+/**
+ * api_cmd_create_cell - create API CMD cell of specific chain
+ * @chain: the API CMD specific chain to create its cell
+ * @cell_idx: the cell index to create
+ * @pre_node: previous cell
+ * @node_vaddr: the virt addr of the cell
+ * Return: 0 - success, negative - failure
+ **/
+static int api_cmd_create_cell(struct hifc_api_cmd_chain *chain, u32 cell_idx,
+ struct hifc_api_cmd_cell *pre_node,
+ struct hifc_api_cmd_cell **node_vaddr)
+{
+ struct hifc_api_cmd_cell_ctxt *cell_ctxt;
+ struct hifc_api_cmd_cell *node;
+ void *cell_vaddr;
+ u64 cell_paddr;
+ int err;
+
+ cell_vaddr = (void *)((u64)chain->cell_vaddr_base +
+ chain->cell_size_align * cell_idx);
+ cell_paddr = chain->cell_paddr_base +
+ chain->cell_size_align * cell_idx;
+
+ cell_ctxt = &chain->cell_ctxt[cell_idx];
+ cell_ctxt->cell_vaddr = cell_vaddr;
+ node = cell_ctxt->cell_vaddr;
+
+ if (!pre_node) {
+ chain->head_node = cell_vaddr;
+ chain->head_cell_paddr = cell_paddr;
+ } else {
+ /* The data in the HW should be in Big Endian Format */
+ pre_node->next_cell_paddr = cpu_to_be64(cell_paddr);
+ }
+
+ /* Driver software should make sure that there is an empty API
+ * command cell at the end the chain
+ */
+ node->next_cell_paddr = 0;
+
+ err = hifc_alloc_api_cmd_cell_buf(chain, cell_idx, node);
+ if (err)
+ return err;
+
+ *node_vaddr = node;
+
+ return 0;
+}
+
+/**
+ * api_cmd_create_cells - create API CMD cells for specific chain
+ * @chain: the API CMD specific chain
+ * Return: 0 - success, negative - failure
+ **/
+static int api_cmd_create_cells(struct hifc_api_cmd_chain *chain)
+{
+ struct hifc_api_cmd_cell *node = NULL, *pre_node = NULL;
+ void *dev = chain->hwdev->dev_hdl;
+ u32 cell_idx;
+ int err;
+
+ for (cell_idx = 0; cell_idx < chain->num_cells; cell_idx++) {
+ err = api_cmd_create_cell(chain, cell_idx, pre_node, &node);
+ if (err) {
+ sdk_err(dev, "Failed to create API CMD cell\n");
+ return err;
+ }
+
+ pre_node = node;
+ }
+
+ if (!node)
+ return -EFAULT;
+
+ /* set the Final node to point on the start */
+ node->next_cell_paddr = cpu_to_be64(chain->head_cell_paddr);
+
+ /* set the current node to be the head */
+ chain->curr_node = chain->head_node;
+ return 0;
+}
+
+/**
+ * api_chain_init - initialize API CMD specific chain
+ * @chain: the API CMD specific chain to initialize
+ * @attr: attributes to set in the chain
+ * Return: 0 - success, negative - failure
+ **/
+static int api_chain_init(struct hifc_api_cmd_chain *chain,
+ struct hifc_api_cmd_chain_attr *attr)
+{
+ void *dev = chain->hwdev->dev_hdl;
+ size_t cell_ctxt_size;
+ size_t cells_buf_size;
+ int err;
+
+ chain->chain_type = attr->chain_type;
+ chain->num_cells = attr->num_cells;
+ chain->cell_size = attr->cell_size;
+ chain->rsp_size = attr->rsp_size;
+
+ chain->prod_idx = 0;
+ chain->cons_idx = 0;
+
+ if (chain->chain_type == HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU)
+ spin_lock_init(&chain->async_lock);
+ else
+ sema_init(&chain->sem, 1);
+
+ cell_ctxt_size = chain->num_cells * sizeof(*chain->cell_ctxt);
+ if (!cell_ctxt_size) {
+ sdk_err(dev, "Api chain cell size cannot be zero\n");
+ err = -EINVAL;
+ goto alloc_cell_ctxt_err;
+ }
+
+ chain->cell_ctxt = kzalloc(cell_ctxt_size, GFP_KERNEL);
+ if (!chain->cell_ctxt) {
+ sdk_err(dev, "Failed to allocate cell contexts for a chain\n");
+ err = -ENOMEM;
+ goto alloc_cell_ctxt_err;
+ }
+
+ chain->wb_status = dma_zalloc_coherent(dev,
+ sizeof(*chain->wb_status),
+ &chain->wb_status_paddr,
+ GFP_KERNEL);
+ if (!chain->wb_status) {
+ sdk_err(dev, "Failed to allocate DMA wb status\n");
+ err = -ENOMEM;
+ goto alloc_wb_status_err;
+ }
+
+ chain->cell_size_align = ALIGN((u64)chain->cell_size,
+ API_CMD_NODE_ALIGN_SIZE);
+ chain->rsp_size_align = ALIGN((u64)chain->rsp_size,
+ API_CHAIN_RESP_ALIGNMENT);
+ chain->buf_size_align = ALIGN(API_CMD_BUF_SIZE, API_PAYLOAD_ALIGN_SIZE);
+
+ cells_buf_size = (chain->cell_size_align + chain->rsp_size_align +
+ chain->buf_size_align) * chain->num_cells;
+
+ err = hifc_dma_zalloc_coherent_align(dev, cells_buf_size,
+ API_CMD_NODE_ALIGN_SIZE,
+ GFP_KERNEL,
+ &chain->cells_addr);
+ if (err) {
+ sdk_err(dev, "Failed to allocate API CMD cells buffer\n");
+ goto alloc_cells_buf_err;
+ }
+
+ chain->cell_vaddr_base = chain->cells_addr.align_vaddr;
+ chain->cell_paddr_base = chain->cells_addr.align_paddr;
+
+ chain->rsp_vaddr_base = (u8 *)((u64)chain->cell_vaddr_base +
+ chain->cell_size_align * chain->num_cells);
+ chain->rsp_paddr_base = chain->cell_paddr_base +
+ chain->cell_size_align * chain->num_cells;
+
+ chain->buf_vaddr_base = (u8 *)((u64)chain->rsp_vaddr_base +
+ chain->rsp_size_align * chain->num_cells);
+ chain->buf_paddr_base = chain->rsp_paddr_base +
+ chain->rsp_size_align * chain->num_cells;
+
+ return 0;
+
+alloc_cells_buf_err:
+ dma_free_coherent(dev, sizeof(*chain->wb_status),
+ chain->wb_status, chain->wb_status_paddr);
+
+alloc_wb_status_err:
+ kfree(chain->cell_ctxt);
+
+alloc_cell_ctxt_err:
+ return err;
+}
+
+/**
+ * api_chain_free - free API CMD specific chain
+ * @chain: the API CMD specific chain to free
+ **/
+static void api_chain_free(struct hifc_api_cmd_chain *chain)
+{
+ void *dev = chain->hwdev->dev_hdl;
+
+ hifc_dma_free_coherent_align(dev, &chain->cells_addr);
+
+ dma_free_coherent(dev, sizeof(*chain->wb_status),
+ chain->wb_status, chain->wb_status_paddr);
+ kfree(chain->cell_ctxt);
+}
+
+/**
+ * api_cmd_create_chain - create API CMD specific chain
+ * @chain: the API CMD specific chain to create
+ * @attr: attributes to set in the chain
+ * Return: 0 - success, negative - failure
+ **/
+static int api_cmd_create_chain(struct hifc_api_cmd_chain **cmd_chain,
+ struct hifc_api_cmd_chain_attr *attr)
+{
+ struct hifc_hwdev *hwdev = attr->hwdev;
+ struct hifc_api_cmd_chain *chain;
+ int err;
+
+ if (attr->num_cells & (attr->num_cells - 1)) {
+ sdk_err(hwdev->dev_hdl, "Invalid number of cells, must be power of 2\n");
+ return -EINVAL;
+ }
+
+ chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+ if (!chain)
+ return -ENOMEM;
+
+ chain->hwdev = hwdev;
+
+ err = api_chain_init(chain, attr);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to initialize chain\n");
+ goto chain_init_err;
+ }
+
+ err = api_cmd_create_cells(chain);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to create cells for API CMD chain\n");
+ goto create_cells_err;
+ }
+
+ err = api_cmd_chain_hw_init(chain);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to initialize chain HW\n");
+ goto chain_hw_init_err;
+ }
+
+ *cmd_chain = chain;
+ return 0;
+
+chain_hw_init_err:
+create_cells_err:
+ api_chain_free(chain);
+
+chain_init_err:
+ kfree(chain);
+ return err;
+}
+
+/**
+ * api_cmd_destroy_chain - destroy API CMD specific chain
+ * @chain: the API CMD specific chain to destroy
+ **/
+static void api_cmd_destroy_chain(struct hifc_api_cmd_chain *chain)
+{
+ api_chain_free(chain);
+ kfree(chain);
+}
+
+/**
+ * hifc_api_cmd_init - Initialize all the API CMD chains
+ * @hwdev: the pointer to hw device
+ * @chain: the API CMD chains that will be initialized
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_api_cmd_init(struct hifc_hwdev *hwdev,
+ struct hifc_api_cmd_chain **chain)
+{
+ void *dev = hwdev->dev_hdl;
+ struct hifc_api_cmd_chain_attr attr;
+ enum hifc_api_cmd_chain_type chain_type, i;
+ int err;
+
+ attr.hwdev = hwdev;
+ attr.num_cells = API_CHAIN_NUM_CELLS;
+ attr.cell_size = API_CHAIN_CELL_SIZE;
+ attr.rsp_size = API_CHAIN_RSP_DATA_SIZE;
+
+ chain_type = HIFC_API_CMD_WRITE_TO_MGMT_CPU;
+ for (; chain_type < HIFC_API_CMD_MAX; chain_type++) {
+ attr.chain_type = chain_type;
+
+ err = api_cmd_create_chain(&chain[chain_type], &attr);
+ if (err) {
+ sdk_err(dev, "Failed to create chain %d\n", chain_type);
+ goto create_chain_err;
+ }
+ }
+
+ return 0;
+
+create_chain_err:
+ i = HIFC_API_CMD_WRITE_TO_MGMT_CPU;
+ for (; i < chain_type; i++)
+ api_cmd_destroy_chain(chain[i]);
+
+ return err;
+}
+
+/**
+ * hifc_api_cmd_free - free the API CMD chains
+ * @chain: the API CMD chains that will be freed
+ **/
+void hifc_api_cmd_free(struct hifc_api_cmd_chain **chain)
+{
+ enum hifc_api_cmd_chain_type chain_type;
+
+ chain_type = HIFC_API_CMD_WRITE_TO_MGMT_CPU;
+
+ for (; chain_type < HIFC_API_CMD_MAX; chain_type++)
+ api_cmd_destroy_chain(chain[chain_type]);
+}
+
diff --git a/drivers/scsi/huawei/hifc/hifc_api_cmd.h b/drivers/scsi/huawei/hifc/hifc_api_cmd.h
new file mode 100644
index 000000000000..bd14db34a119
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_api_cmd.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_API_CMD_H_
+#define HIFC_API_CMD_H_
+
+#define HIFC_API_CMD_CELL_CTRL_CELL_LEN_SHIFT 0
+#define HIFC_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_SHIFT 16
+#define HIFC_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_SHIFT 24
+#define HIFC_API_CMD_CELL_CTRL_XOR_CHKSUM_SHIFT 56
+
+#define HIFC_API_CMD_CELL_CTRL_CELL_LEN_MASK 0x3FU
+#define HIFC_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_MASK 0x3FU
+#define HIFC_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_MASK 0x3FU
+#define HIFC_API_CMD_CELL_CTRL_XOR_CHKSUM_MASK 0xFFU
+
+#define HIFC_API_CMD_CELL_CTRL_SET(val, member) \
+ ((((u64)val) & HIFC_API_CMD_CELL_CTRL_##member##_MASK) << \
+ HIFC_API_CMD_CELL_CTRL_##member##_SHIFT)
+
+#define HIFC_API_CMD_DESC_API_TYPE_SHIFT 0
+#define HIFC_API_CMD_DESC_RD_WR_SHIFT 1
+#define HIFC_API_CMD_DESC_MGMT_BYPASS_SHIFT 2
+#define HIFC_API_CMD_DESC_RESP_AEQE_EN_SHIFT 3
+#define HIFC_API_CMD_DESC_PRIV_DATA_SHIFT 8
+#define HIFC_API_CMD_DESC_DEST_SHIFT 32
+#define HIFC_API_CMD_DESC_SIZE_SHIFT 40
+#define HIFC_API_CMD_DESC_XOR_CHKSUM_SHIFT 56
+
+#define HIFC_API_CMD_DESC_API_TYPE_MASK 0x1U
+#define HIFC_API_CMD_DESC_RD_WR_MASK 0x1U
+#define HIFC_API_CMD_DESC_MGMT_BYPASS_MASK 0x1U
+#define HIFC_API_CMD_DESC_RESP_AEQE_EN_MASK 0x1U
+#define HIFC_API_CMD_DESC_DEST_MASK 0x1FU
+#define HIFC_API_CMD_DESC_SIZE_MASK 0x7FFU
+#define HIFC_API_CMD_DESC_XOR_CHKSUM_MASK 0xFFU
+#define HIFC_API_CMD_DESC_PRIV_DATA_MASK 0xFFFFFFU
+
+#define HIFC_API_CMD_DESC_SET(val, member) \
+ ((((u64)val) & HIFC_API_CMD_DESC_##member##_MASK) << \
+ HIFC_API_CMD_DESC_##member##_SHIFT)
+#define HIFC_API_CMD_STATUS_HEADER_VALID_SHIFT 0
+#define HIFC_API_CMD_STATUS_HEADER_CHAIN_ID_SHIFT 16
+
+#define HIFC_API_CMD_STATUS_HEADER_VALID_MASK 0xFFU
+#define HIFC_API_CMD_STATUS_HEADER_CHAIN_ID_MASK 0xFFU
+#define HIFC_API_CMD_STATUS_HEADER_GET(val, member) \
+ (((val) >> HIFC_API_CMD_STATUS_HEADER_##member##_SHIFT) & \
+ HIFC_API_CMD_STATUS_HEADER_##member##_MASK)
+#define HIFC_API_CMD_CHAIN_REQ_RESTART_SHIFT 1
+#define HIFC_API_CMD_CHAIN_REQ_RESTART_MASK 0x1U
+#define HIFC_API_CMD_CHAIN_REQ_WB_TRIGGER_MASK 0x1U
+#define HIFC_API_CMD_CHAIN_REQ_SET(val, member) \
+ (((val) & HIFC_API_CMD_CHAIN_REQ_##member##_MASK) << \
+ HIFC_API_CMD_CHAIN_REQ_##member##_SHIFT)
+
+#define HIFC_API_CMD_CHAIN_REQ_GET(val, member) \
+ (((val) >> HIFC_API_CMD_CHAIN_REQ_##member##_SHIFT) & \
+ HIFC_API_CMD_CHAIN_REQ_##member##_MASK)
+
+#define HIFC_API_CMD_CHAIN_REQ_CLEAR(val, member) \
+ ((val) & (~(HIFC_API_CMD_CHAIN_REQ_##member##_MASK \
+ << HIFC_API_CMD_CHAIN_REQ_##member##_SHIFT)))
+
+#define HIFC_API_CMD_CHAIN_CTRL_RESTART_EN_SHIFT 1
+#define HIFC_API_CMD_CHAIN_CTRL_XOR_ERR_SHIFT 2
+#define HIFC_API_CMD_CHAIN_CTRL_AEQE_EN_SHIFT 4
+#define HIFC_API_CMD_CHAIN_CTRL_AEQ_ID_SHIFT 8
+#define HIFC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_SHIFT 28
+#define HIFC_API_CMD_CHAIN_CTRL_CELL_SIZE_SHIFT 30
+
+#define HIFC_API_CMD_CHAIN_CTRL_RESTART_EN_MASK 0x1U
+#define HIFC_API_CMD_CHAIN_CTRL_XOR_ERR_MASK 0x1U
+#define HIFC_API_CMD_CHAIN_CTRL_AEQE_EN_MASK 0x1U
+#define HIFC_API_CMD_CHAIN_CTRL_AEQ_ID_MASK 0x3U
+#define HIFC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_MASK 0x3U
+#define HIFC_API_CMD_CHAIN_CTRL_CELL_SIZE_MASK 0x3U
+
+#define HIFC_API_CMD_CHAIN_CTRL_SET(val, member) \
+ (((val) & HIFC_API_CMD_CHAIN_CTRL_##member##_MASK) << \
+ HIFC_API_CMD_CHAIN_CTRL_##member##_SHIFT)
+
+#define HIFC_API_CMD_CHAIN_CTRL_CLEAR(val, member) \
+ ((val) & (~(HIFC_API_CMD_CHAIN_CTRL_##member##_MASK \
+ << HIFC_API_CMD_CHAIN_CTRL_##member##_SHIFT)))
+
+#define HIFC_API_CMD_RESP_HEAD_VALID_MASK 0xFF
+#define HIFC_API_CMD_RESP_HEAD_VALID_CODE 0xFF
+
+#define HIFC_API_CMD_RESP_HEADER_VALID(val) \
+ (((val) & HIFC_API_CMD_RESP_HEAD_VALID_MASK) == \
+ HIFC_API_CMD_RESP_HEAD_VALID_CODE)
+#define HIFC_API_CMD_STATUS_CONS_IDX_MASK 0xFFFFFFU
+#define HIFC_API_CMD_STATUS_CONS_IDX_SHIFT 0
+#define HIFC_API_CMD_STATUS_FSM_MASK 0xFU
+#define HIFC_API_CMD_STATUS_FSM_SHIFT 24
+#define HIFC_API_CMD_STATUS_CHKSUM_ERR_MASK 0x3U
+#define HIFC_API_CMD_STATUS_CHKSUM_ERR_SHIFT 28
+#define HIFC_API_CMD_STATUS_CPLD_ERR_MASK 0x1U
+#define HIFC_API_CMD_STATUS_CPLD_ERR_SHIFT 30
+
+#define HIFC_API_CMD_STATUS_GET(val, member) \
+ (((val) >> HIFC_API_CMD_STATUS_##member##_SHIFT) & \
+ HIFC_API_CMD_STATUS_##member##_MASK)
+
+/* API CMD registers */
+#define HIFC_CSR_API_CMD_BASE 0xF000
+
+#define HIFC_CSR_API_CMD_STRIDE 0x100
+
+#define HIFC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x0 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x4 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_STATUS_HI_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x8 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_STATUS_LO_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0xC + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x10 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_CHAIN_CTRL_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x14 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_CHAIN_PI_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x1C + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_CHAIN_REQ_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x20 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+#define HIFC_CSR_API_CMD_STATUS_0_ADDR(idx) \
+ (HIFC_CSR_API_CMD_BASE + 0x30 + (idx) * HIFC_CSR_API_CMD_STRIDE)
+
+enum hifc_api_cmd_chain_type {
+ /* write command with completion notification */
+ HIFC_API_CMD_WRITE = 0,
+ /* read command with completion notification */
+ HIFC_API_CMD_READ = 1,
+ /* write to mgmt cpu command with completion */
+ HIFC_API_CMD_WRITE_TO_MGMT_CPU = 2,
+ /* multi read command with completion notification - not used */
+ HIFC_API_CMD_MULTI_READ = 3,
+ /* write command without completion notification */
+ HIFC_API_CMD_POLL_WRITE = 4,
+ /* read command without completion notification */
+ HIFC_API_CMD_POLL_READ = 5,
+ /* read from mgmt cpu command with completion */
+ HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU = 6,
+ HIFC_API_CMD_MAX,
+};
+
+struct hifc_api_cmd_status {
+ u64 header;
+ u32 buf_desc;
+ u32 cell_addr_hi;
+ u32 cell_addr_lo;
+ u32 rsvd0;
+ u64 rsvd1;
+};
+
+/* HW struct */
+struct hifc_api_cmd_cell {
+ u64 ctrl;
+
+ /* address is 64 bit in HW struct */
+ u64 next_cell_paddr;
+
+ u64 desc;
+
+ /* HW struct */
+ union {
+ struct {
+ u64 hw_cmd_paddr;
+ } write;
+
+ struct {
+ u64 hw_wb_resp_paddr;
+ u64 hw_cmd_paddr;
+ } read;
+ };
+};
+
+struct hifc_api_cmd_resp_fmt {
+ u64 header;
+ u64 rsvd[3];
+ u64 resp_data;
+};
+
+struct hifc_api_cmd_cell_ctxt {
+ struct hifc_api_cmd_cell *cell_vaddr;
+
+ void *api_cmd_vaddr;
+
+ struct hifc_api_cmd_resp_fmt *resp;
+
+ struct completion done;
+ int status;
+
+ u32 saved_prod_idx;
+};
+
+struct hifc_api_cmd_chain_attr {
+ struct hifc_hwdev *hwdev;
+ enum hifc_api_cmd_chain_type chain_type;
+
+ u32 num_cells;
+ u16 rsp_size;
+ u16 cell_size;
+};
+
+struct hifc_api_cmd_chain {
+ struct hifc_hwdev *hwdev;
+ enum hifc_api_cmd_chain_type chain_type;
+
+ u32 num_cells;
+ u16 cell_size;
+ u16 rsp_size;
+
+ /* HW members is 24 bit format */
+ u32 prod_idx;
+ u32 cons_idx;
+
+ struct semaphore sem;
+ /* Async cmd can not be scheduling */
+ spinlock_t async_lock;
+
+ dma_addr_t wb_status_paddr;
+ struct hifc_api_cmd_status *wb_status;
+
+ dma_addr_t head_cell_paddr;
+ struct hifc_api_cmd_cell *head_node;
+
+ struct hifc_api_cmd_cell_ctxt *cell_ctxt;
+ struct hifc_api_cmd_cell *curr_node;
+
+ struct hifc_dma_addr_align cells_addr;
+
+ u8 *cell_vaddr_base;
+ u64 cell_paddr_base;
+ u8 *rsp_vaddr_base;
+ u64 rsp_paddr_base;
+ u8 *buf_vaddr_base;
+ u64 buf_paddr_base;
+ u64 cell_size_align;
+ u64 rsp_size_align;
+ u64 buf_size_align;
+};
+
+int hifc_api_cmd_write(struct hifc_api_cmd_chain *chain,
+ enum hifc_node_id dest, void *cmd, u16 size);
+
+int hifc_api_cmd_read(struct hifc_api_cmd_chain *chain,
+ enum hifc_node_id dest, void *cmd, u16 size,
+ void *ack, u16 ack_size);
+
+int hifc_api_cmd_init(struct hifc_hwdev *hwdev,
+ struct hifc_api_cmd_chain **chain);
+
+void hifc_api_cmd_free(struct hifc_api_cmd_chain **chain);
+
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_cfg.c b/drivers/scsi/huawei/hifc/hifc_cfg.c
new file mode 100644
index 000000000000..5ebe5d754c41
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cfg.c
@@ -0,0 +1,823 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/semaphore.h>
+#include <linux/vmalloc.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_cqm_main.h"
+#include "hifc_api_cmd.h"
+#include "hifc_hw.h"
+#include "hifc_mgmt.h"
+#include "hifc_cfg.h"
+
+uint intr_mode;
+
+int hifc_sync_time(void *hwdev, u64 time)
+{
+ struct hifc_sync_time_info time_info = {0};
+ u16 out_size = sizeof(time_info);
+ int err;
+
+ time_info.mstime = time;
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_SYNC_TIME, &time_info,
+ sizeof(time_info), &time_info, &out_size,
+ 0);
+ if (err || time_info.status || !out_size) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to sync time to mgmt, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, time_info.status, out_size);
+ }
+
+ return err;
+}
+
+static void parse_pub_res_cap(struct service_cap *cap,
+ struct hifc_dev_cap *dev_cap,
+ enum func_type type)
+{
+ cap->port_id = dev_cap->port_id;
+ cap->force_up = dev_cap->force_up;
+
+ pr_info("Get public resource capbility, force_up: 0x%x\n",
+ cap->force_up);
+ /* FC need max queue number, but max queue number info is in
+ * l2nic cap, we also put max queue num info in public cap, so
+ * FC can get correct max queue number info.
+ */
+ cap->max_sqs = dev_cap->nic_max_sq + 1;
+ cap->max_rqs = dev_cap->nic_max_rq + 1;
+
+ cap->host_total_function = dev_cap->host_total_func;
+ cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val;
+ cap->max_connect_num = dev_cap->max_conn_num;
+ cap->max_stick2cache_num = dev_cap->max_stick2cache_num;
+
+ pr_info("Get public resource capbility, svc_cap_en: 0x%x\n",
+ dev_cap->svc_cap_en);
+ pr_info("port_id=0x%x\n", cap->port_id);
+ pr_info("Host_total_function=0x%x, host_oq_id_mask_val=0x%x\n",
+ cap->host_total_function, cap->host_oq_id_mask_val);
+}
+
+static void parse_fc_res_cap(struct service_cap *cap,
+ struct hifc_dev_cap *dev_cap,
+ enum func_type type)
+{
+ struct dev_fc_svc_cap *fc_cap = &cap->fc_cap.dev_fc_cap;
+
+ fc_cap->max_parent_qpc_num = dev_cap->fc_max_pctx;
+ fc_cap->scq_num = dev_cap->fc_max_scq;
+ fc_cap->srq_num = dev_cap->fc_max_srq;
+ fc_cap->max_child_qpc_num = dev_cap->fc_max_cctx;
+ fc_cap->vp_id_start = dev_cap->fc_vp_id_start;
+ fc_cap->vp_id_end = dev_cap->fc_vp_id_end;
+
+ pr_info("Get fc resource capbility\n");
+ pr_info("Max_parent_qpc_num=0x%x, scq_num=0x%x, srq_num=0x%x, max_child_qpc_num=0x%x\n",
+ fc_cap->max_parent_qpc_num, fc_cap->scq_num, fc_cap->srq_num,
+ fc_cap->max_child_qpc_num);
+ pr_info("Vp_id_start=0x%x, vp_id_end=0x%x\n",
+ fc_cap->vp_id_start, fc_cap->vp_id_end);
+}
+
+static void parse_dev_cap(struct hifc_hwdev *dev,
+ struct hifc_dev_cap *dev_cap, enum func_type type)
+{
+ struct service_cap *cap = &dev->cfg_mgmt->svc_cap;
+
+ /* Public resource */
+ parse_pub_res_cap(cap, dev_cap, type);
+
+ /* PPF managed dynamic resource */
+
+ parse_fc_res_cap(cap, dev_cap, type);
+}
+
+static int get_cap_from_fw(struct hifc_hwdev *dev, enum func_type type)
+{
+ struct hifc_dev_cap dev_cap = {0};
+ u16 out_len = sizeof(dev_cap);
+ int err;
+
+ dev_cap.version = HIFC_CMD_VER_FUNC_ID;
+ err = hifc_global_func_id_get(dev, &dev_cap.func_id);
+ if (err)
+ return err;
+
+ sdk_info(dev->dev_hdl, "Get cap from fw, func_idx: %d\n",
+ dev_cap.func_id);
+
+ err = hifc_msg_to_mgmt_sync(dev, HIFC_MOD_CFGM, HIFC_CFG_NIC_CAP,
+ &dev_cap, sizeof(dev_cap),
+ &dev_cap, &out_len, 0);
+ if (err || dev_cap.status || !out_len) {
+ sdk_err(dev->dev_hdl,
+ "Failed to get capability from FW, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, dev_cap.status, out_len);
+ return -EFAULT;
+ }
+
+ parse_dev_cap(dev, &dev_cap, type);
+ return 0;
+}
+
+static void fc_param_fix(struct hifc_hwdev *dev)
+{
+ struct service_cap *cap = &dev->cfg_mgmt->svc_cap;
+ struct fc_service_cap *fc_cap = &cap->fc_cap;
+
+ fc_cap->parent_qpc_size = FC_PCTX_SZ;
+ fc_cap->child_qpc_size = FC_CCTX_SZ;
+ fc_cap->sqe_size = FC_SQE_SZ;
+
+ fc_cap->scqc_size = FC_SCQC_SZ;
+ fc_cap->scqe_size = FC_SCQE_SZ;
+
+ fc_cap->srqc_size = FC_SRQC_SZ;
+ fc_cap->srqe_size = FC_SRQE_SZ;
+}
+
+static void cfg_get_eq_num(struct hifc_hwdev *dev)
+{
+ struct cfg_eq_info *eq_info = &dev->cfg_mgmt->eq_info;
+
+ eq_info->num_ceq = dev->hwif->attr.num_ceqs;
+ eq_info->num_ceq_remain = eq_info->num_ceq;
+}
+
+static int cfg_init_eq(struct hifc_hwdev *dev)
+{
+ struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt;
+ struct cfg_eq *eq;
+ u8 num_ceq, i = 0;
+
+ cfg_get_eq_num(dev);
+ num_ceq = cfg_mgmt->eq_info.num_ceq;
+
+ sdk_info(dev->dev_hdl, "Cfg mgmt: ceqs=0x%x, remain=0x%x\n",
+ cfg_mgmt->eq_info.num_ceq, cfg_mgmt->eq_info.num_ceq_remain);
+
+ if (!num_ceq) {
+ sdk_err(dev->dev_hdl, "Ceq num cfg in fw is zero\n");
+ return -EFAULT;
+ }
+ eq = kcalloc(num_ceq, sizeof(*eq), GFP_KERNEL);
+ if (!eq)
+ return -ENOMEM;
+
+ for (i = 0; i < num_ceq; ++i) {
+ eq[i].eqn = i;
+ eq[i].free = CFG_FREE;
+ eq[i].type = SERVICE_T_MAX;
+ }
+
+ cfg_mgmt->eq_info.eq = eq;
+
+ mutex_init(&cfg_mgmt->eq_info.eq_mutex);
+
+ return 0;
+}
+
+static int cfg_init_interrupt(struct hifc_hwdev *dev)
+{
+ struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt;
+ struct cfg_irq_info *irq_info = &cfg_mgmt->irq_param_info;
+ u16 intr_num = dev->hwif->attr.num_irqs;
+
+ if (!intr_num) {
+ sdk_err(dev->dev_hdl, "Irq num cfg in fw is zero\n");
+ return -EFAULT;
+ }
+ irq_info->alloc_info = kcalloc(intr_num, sizeof(*irq_info->alloc_info),
+ GFP_KERNEL);
+ if (!irq_info->alloc_info)
+ return -ENOMEM;
+
+ irq_info->num_irq_hw = intr_num;
+
+ cfg_mgmt->svc_cap.interrupt_type = intr_mode;
+
+ mutex_init(&irq_info->irq_mutex);
+
+ return 0;
+}
+
+static int cfg_enable_interrupt(struct hifc_hwdev *dev)
+{
+ struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt;
+ u16 nreq = cfg_mgmt->irq_param_info.num_irq_hw;
+
+ void *pcidev = dev->pcidev_hdl;
+ struct irq_alloc_info_st *irq_info;
+ struct msix_entry *entry;
+ u16 i = 0;
+ int actual_irq;
+
+ irq_info = cfg_mgmt->irq_param_info.alloc_info;
+
+ sdk_info(dev->dev_hdl, "Interrupt type: %d, irq num: %d.\n",
+ cfg_mgmt->svc_cap.interrupt_type, nreq);
+
+ switch (cfg_mgmt->svc_cap.interrupt_type) {
+ case INTR_TYPE_MSIX:
+
+ if (!nreq) {
+ sdk_err(dev->dev_hdl, "Interrupt number cannot be zero\n");
+ return -EINVAL;
+ }
+ entry = kcalloc(nreq, sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ for (i = 0; i < nreq; i++)
+ entry[i].entry = i;
+
+ actual_irq = pci_enable_msix_range(pcidev, entry,
+ VECTOR_THRESHOLD, nreq);
+ if (actual_irq < 0) {
+ sdk_err(dev->dev_hdl, "Alloc msix entries with threshold 2 failed.\n");
+ kfree(entry);
+ return -ENOMEM;
+ }
+
+ nreq = (u16)actual_irq;
+ cfg_mgmt->irq_param_info.num_total = nreq;
+ cfg_mgmt->irq_param_info.num_irq_remain = nreq;
+ sdk_info(dev->dev_hdl, "Request %d msix vector success.\n",
+ nreq);
+
+ for (i = 0; i < nreq; ++i) {
+ /* u16 driver uses to specify entry, OS writes */
+ irq_info[i].info.msix_entry_idx = entry[i].entry;
+ /* u32 kernel uses to write allocated vector */
+ irq_info[i].info.irq_id = entry[i].vector;
+ irq_info[i].type = SERVICE_T_MAX;
+ irq_info[i].free = CFG_FREE;
+ }
+
+ kfree(entry);
+
+ break;
+
+ default:
+ sdk_err(dev->dev_hdl, "Unsupport interrupt type %d\n",
+ cfg_mgmt->svc_cap.interrupt_type);
+ break;
+ }
+
+ return 0;
+}
+
+int hifc_alloc_irqs(void *hwdev, enum hifc_service_type type, u16 num,
+ struct irq_info *irq_info_array, u16 *act_num)
+{
+ struct hifc_hwdev *dev = hwdev;
+ struct cfg_mgmt_info *cfg_mgmt;
+ struct cfg_irq_info *irq_info;
+ struct irq_alloc_info_st *alloc_info;
+ int max_num_irq;
+ u16 free_num_irq;
+ int i, j;
+
+ if (!hwdev || !irq_info_array || !act_num)
+ return -EINVAL;
+
+ cfg_mgmt = dev->cfg_mgmt;
+ irq_info = &cfg_mgmt->irq_param_info;
+ alloc_info = irq_info->alloc_info;
+ max_num_irq = irq_info->num_total;
+ free_num_irq = irq_info->num_irq_remain;
+
+ mutex_lock(&irq_info->irq_mutex);
+
+ if (num > free_num_irq) {
+ if (free_num_irq == 0) {
+ sdk_err(dev->dev_hdl,
+ "no free irq resource in cfg mgmt.\n");
+ mutex_unlock(&irq_info->irq_mutex);
+ return -ENOMEM;
+ }
+
+ sdk_warn(dev->dev_hdl, "only %d irq resource in cfg mgmt.\n",
+ free_num_irq);
+ num = free_num_irq;
+ }
+
+ *act_num = 0;
+
+ for (i = 0; i < num; i++) {
+ for (j = 0; j < max_num_irq; j++) {
+ if (alloc_info[j].free == CFG_FREE) {
+ if (irq_info->num_irq_remain == 0) {
+ sdk_err(dev->dev_hdl, "No free irq resource in cfg mgmt\n");
+ mutex_unlock(&irq_info->irq_mutex);
+ return -EINVAL;
+ }
+ alloc_info[j].type = type;
+ alloc_info[j].free = CFG_BUSY;
+
+ irq_info_array[i].msix_entry_idx =
+ alloc_info[j].info.msix_entry_idx;
+ irq_info_array[i].irq_id =
+ alloc_info[j].info.irq_id;
+ (*act_num)++;
+ irq_info->num_irq_remain--;
+
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&irq_info->irq_mutex);
+ return 0;
+}
+
+void hifc_free_irq(void *hwdev, enum hifc_service_type type, u32 irq_id)
+{
+ struct hifc_hwdev *dev = hwdev;
+ struct cfg_mgmt_info *cfg_mgmt;
+ struct cfg_irq_info *irq_info;
+ struct irq_alloc_info_st *alloc_info;
+ int max_num_irq;
+ int i;
+
+ if (!hwdev)
+ return;
+
+ cfg_mgmt = dev->cfg_mgmt;
+ irq_info = &cfg_mgmt->irq_param_info;
+ alloc_info = irq_info->alloc_info;
+ max_num_irq = irq_info->num_total;
+
+ mutex_lock(&irq_info->irq_mutex);
+
+ for (i = 0; i < max_num_irq; i++) {
+ if (irq_id == alloc_info[i].info.irq_id &&
+ type == alloc_info[i].type) {
+ if (alloc_info[i].free == CFG_BUSY) {
+ alloc_info[i].free = CFG_FREE;
+ irq_info->num_irq_remain++;
+ if (irq_info->num_irq_remain > max_num_irq) {
+ sdk_err(dev->dev_hdl, "Find target,but over range\n");
+ mutex_unlock(&irq_info->irq_mutex);
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ if (i >= max_num_irq)
+ sdk_warn(dev->dev_hdl, "Irq %d don`t need to free\n", irq_id);
+
+ mutex_unlock(&irq_info->irq_mutex);
+}
+
+int init_cfg_mgmt(struct hifc_hwdev *dev)
+{
+ int err;
+ struct cfg_mgmt_info *cfg_mgmt;
+
+ cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL);
+ if (!cfg_mgmt)
+ return -ENOMEM;
+
+ dev->cfg_mgmt = cfg_mgmt;
+ cfg_mgmt->hwdev = dev;
+
+ err = cfg_init_eq(dev);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Failed to init cfg event queue, err: %d\n",
+ err);
+ goto free_mgmt_mem;
+ }
+
+ err = cfg_init_interrupt(dev);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Failed to init cfg interrupt, err: %d\n",
+ err);
+ goto free_eq_mem;
+ }
+
+ err = cfg_enable_interrupt(dev);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Failed to enable cfg interrupt, err: %d\n",
+ err);
+ goto free_interrupt_mem;
+ }
+
+ return 0;
+
+free_interrupt_mem:
+ kfree(cfg_mgmt->irq_param_info.alloc_info);
+
+ cfg_mgmt->irq_param_info.alloc_info = NULL;
+
+free_eq_mem:
+ kfree(cfg_mgmt->eq_info.eq);
+
+ cfg_mgmt->eq_info.eq = NULL;
+
+free_mgmt_mem:
+ kfree(cfg_mgmt);
+ return err;
+}
+
+void free_cfg_mgmt(struct hifc_hwdev *dev)
+{
+ struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt;
+
+ /* if the allocated resource were recycled */
+ if (cfg_mgmt->irq_param_info.num_irq_remain !=
+ cfg_mgmt->irq_param_info.num_total ||
+ cfg_mgmt->eq_info.num_ceq_remain != cfg_mgmt->eq_info.num_ceq)
+ sdk_err(dev->dev_hdl, "Can't reclaim all irq and event queue, please check\n");
+
+ switch (cfg_mgmt->svc_cap.interrupt_type) {
+ case INTR_TYPE_MSIX:
+ pci_disable_msix(dev->pcidev_hdl);
+ break;
+
+ case INTR_TYPE_MSI:
+ pci_disable_msi(dev->pcidev_hdl);
+ break;
+
+ case INTR_TYPE_INT:
+ default:
+ break;
+ }
+
+ kfree(cfg_mgmt->irq_param_info.alloc_info);
+ cfg_mgmt->irq_param_info.alloc_info = NULL;
+
+ kfree(cfg_mgmt->eq_info.eq);
+ cfg_mgmt->eq_info.eq = NULL;
+
+ kfree(cfg_mgmt);
+}
+
+int init_capability(struct hifc_hwdev *dev)
+{
+ int err;
+ enum func_type type = HIFC_FUNC_TYPE(dev);
+ struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt;
+
+ cfg_mgmt->svc_cap.timer_en = 1;
+ cfg_mgmt->svc_cap.test_xid_alloc_mode = 1;
+ cfg_mgmt->svc_cap.test_gpa_check_enable = 1;
+
+ err = get_cap_from_fw(dev, type);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Failed to get PF/PPF capability\n");
+ return err;
+ }
+
+ fc_param_fix(dev);
+
+ if (dev->cfg_mgmt->svc_cap.force_up)
+ dev->feature_cap |= HIFC_FUNC_FORCE_LINK_UP;
+
+ sdk_info(dev->dev_hdl, "Init capability success\n");
+ return 0;
+}
+
+void free_capability(struct hifc_hwdev *dev)
+{
+ sdk_info(dev->dev_hdl, "Free capability success");
+}
+
+bool hifc_support_fc(void *hwdev, struct fc_service_cap *cap)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!hwdev)
+ return false;
+
+ if (cap)
+ memcpy(cap, &dev->cfg_mgmt->svc_cap.fc_cap, sizeof(*cap));
+
+ return true;
+}
+
+u8 hifc_host_oq_id_mask(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!dev) {
+ pr_err("Hwdev pointer is NULL for getting host oq id mask\n");
+ return 0;
+ }
+ return dev->cfg_mgmt->svc_cap.host_oq_id_mask_val;
+}
+
+u16 hifc_func_max_qnum(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!dev) {
+ pr_err("Hwdev pointer is NULL for getting function max queue number\n");
+ return 0;
+ }
+ return dev->cfg_mgmt->svc_cap.max_sqs;
+}
+
+/* Caller should ensure atomicity when calling this function */
+int hifc_stateful_init(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+ int err;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (dev->statufull_ref_cnt++)
+ return 0;
+
+ err = cqm_init(dev);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Failed to init cqm, err: %d\n", err);
+ goto init_cqm_err;
+ }
+
+ sdk_info(dev->dev_hdl, "Initialize statefull resource success\n");
+
+ return 0;
+
+init_cqm_err:
+
+ dev->statufull_ref_cnt--;
+
+ return err;
+}
+
+/* Caller should ensure atomicity when calling this function */
+void hifc_stateful_deinit(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!dev || !dev->statufull_ref_cnt)
+ return;
+
+ if (--dev->statufull_ref_cnt)
+ return;
+
+ cqm_uninit(hwdev);
+
+ sdk_info(dev->dev_hdl, "Clear statefull resource success\n");
+}
+
+bool hifc_is_hwdev_mod_inited(void *hwdev, enum hifc_hwdev_init_state state)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!hwdev || state >= HIFC_HWDEV_MAX_INVAL_INITED)
+ return false;
+
+ return !!test_bit(state, &dev->func_state);
+}
+
+static int hifc_os_dep_init(struct hifc_hwdev *hwdev)
+{
+ hwdev->workq = create_singlethread_workqueue(HIFC_HW_WQ_NAME);
+ if (!hwdev->workq) {
+ sdk_err(hwdev->dev_hdl, "Failed to initialize hardware workqueue\n");
+ return -EFAULT;
+ }
+
+ sema_init(&hwdev->fault_list_sem, 1);
+
+ return 0;
+}
+
+static void hifc_os_dep_deinit(struct hifc_hwdev *hwdev)
+{
+ destroy_workqueue(hwdev->workq);
+}
+
+static int __hilink_phy_init(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = hifc_phy_init_status_judge(hwdev);
+ if (err) {
+ sdk_info(hwdev->dev_hdl, "Phy init failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int init_hwdev_and_hwif(struct hifc_init_para *para)
+{
+ struct hifc_hwdev *hwdev;
+ int err;
+
+ if (!(*para->hwdev)) {
+ hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
+ if (!hwdev)
+ return -ENOMEM;
+
+ *para->hwdev = hwdev;
+ hwdev->adapter_hdl = para->adapter_hdl;
+ hwdev->pcidev_hdl = para->pcidev_hdl;
+ hwdev->dev_hdl = para->dev_hdl;
+ hwdev->chip_node = para->chip_node;
+
+ hwdev->chip_fault_stats = vzalloc(HIFC_CHIP_FAULT_SIZE);
+ if (!hwdev->chip_fault_stats)
+ goto alloc_chip_fault_stats_err;
+
+ err = hifc_init_hwif(hwdev, para->cfg_reg_base,
+ para->intr_reg_base,
+ para->db_base_phy, para->db_base,
+ para->dwqe_mapping);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init hwif\n");
+ goto init_hwif_err;
+ }
+ }
+
+ return 0;
+
+init_hwif_err:
+ vfree(hwdev->chip_fault_stats);
+
+alloc_chip_fault_stats_err:
+
+ *para->hwdev = NULL;
+
+ return -EFAULT;
+}
+
+static void deinit_hwdev_and_hwif(struct hifc_hwdev *hwdev)
+{
+ hifc_free_hwif(hwdev);
+
+ vfree(hwdev->chip_fault_stats);
+
+ kfree(hwdev);
+}
+
+static int init_hw_cfg(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = init_capability(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init capability\n");
+ return err;
+ }
+
+ err = __hilink_phy_init(hwdev);
+ if (err)
+ goto hilink_phy_init_err;
+
+ return 0;
+
+hilink_phy_init_err:
+ free_capability(hwdev);
+
+ return err;
+}
+
+/* Return:
+ * 0: all success
+ * >0: partitial success
+ * <0: all failed
+ */
+int hifc_init_hwdev(struct hifc_init_para *para)
+{
+ struct hifc_hwdev *hwdev;
+ int err;
+
+ err = init_hwdev_and_hwif(para);
+ if (err)
+ return err;
+
+ hwdev = *para->hwdev;
+
+ /* detect slave host according to BAR reg */
+ hwdev->feature_cap = HIFC_FUNC_MGMT | HIFC_FUNC_PORT |
+ HIFC_FUNC_SUPP_RATE_LIMIT | HIFC_FUNC_SUPP_DFX_REG |
+ HIFC_FUNC_SUPP_RX_MODE | HIFC_FUNC_SUPP_SET_VF_MAC_VLAN |
+ HIFC_FUNC_SUPP_CHANGE_MAC;
+
+ err = hifc_os_dep_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init os dependent\n");
+ goto os_dep_init_err;
+ }
+
+ hifc_set_chip_present(hwdev);
+ hifc_init_heartbeat(hwdev);
+
+ err = init_cfg_mgmt(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init config mgmt\n");
+ goto init_cfg_mgmt_err;
+ }
+
+ err = hifc_init_comm_ch(hwdev);
+ if (err) {
+ if (!(hwdev->func_state & HIFC_HWDEV_INIT_MODES_MASK)) {
+ sdk_err(hwdev->dev_hdl, "Failed to init communication channel\n");
+ goto init_comm_ch_err;
+ } else {
+ sdk_err(hwdev->dev_hdl, "Init communication channel partitail failed\n");
+ return hwdev->func_state & HIFC_HWDEV_INIT_MODES_MASK;
+ }
+ }
+
+ err = init_hw_cfg(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init hardware config\n");
+ goto init_hw_cfg_err;
+ }
+
+ set_bit(HIFC_HWDEV_ALL_INITED, &hwdev->func_state);
+
+ sdk_info(hwdev->dev_hdl, "Init hwdev success\n");
+
+ return 0;
+
+init_hw_cfg_err:
+ return (hwdev->func_state & HIFC_HWDEV_INIT_MODES_MASK);
+
+init_comm_ch_err:
+ free_cfg_mgmt(hwdev);
+
+init_cfg_mgmt_err:
+ hifc_destroy_heartbeat(hwdev);
+ hifc_os_dep_deinit(hwdev);
+
+os_dep_init_err:
+ deinit_hwdev_and_hwif(hwdev);
+ *para->hwdev = NULL;
+
+ return -EFAULT;
+}
+
+void hifc_free_hwdev(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+ enum hifc_hwdev_init_state state = HIFC_HWDEV_ALL_INITED;
+ int flag = 0;
+
+ if (!hwdev)
+ return;
+
+ if (test_bit(HIFC_HWDEV_ALL_INITED, &dev->func_state)) {
+ clear_bit(HIFC_HWDEV_ALL_INITED, &dev->func_state);
+
+ /* BM slave function not need to exec rx_tx_flush */
+
+ hifc_func_rx_tx_flush(hwdev);
+
+ free_capability(dev);
+ }
+ while (state > HIFC_HWDEV_NONE_INITED) {
+ if (test_bit(state, &dev->func_state)) {
+ flag = 1;
+ break;
+ }
+ state--;
+ }
+ if (flag) {
+ hifc_uninit_comm_ch(dev);
+ free_cfg_mgmt(dev);
+ hifc_destroy_heartbeat(dev);
+ hifc_os_dep_deinit(dev);
+ }
+ clear_bit(HIFC_HWDEV_NONE_INITED, &dev->func_state);
+
+ deinit_hwdev_and_hwif(dev);
+}
+
+u64 hifc_get_func_feature_cap(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!dev) {
+ pr_err("Hwdev pointer is NULL for getting function feature capability\n");
+ return 0;
+ }
+
+ return dev->feature_cap;
+}
+
diff --git a/drivers/scsi/huawei/hifc/hifc_cfg.h b/drivers/scsi/huawei/hifc/hifc_cfg.h
new file mode 100644
index 000000000000..b8a9dd35b1fd
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cfg.h
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef __CFG_MGT_H__
+#define __CFG_MGT_H__
+
+enum {
+ CFG_FREE = 0,
+ CFG_BUSY = 1
+};
+
+/* FC */
+#define FC_PCTX_SZ 256
+#define FC_CCTX_SZ 256
+#define FC_SQE_SZ 128
+#define FC_SCQC_SZ 64
+#define FC_SCQE_SZ 64
+#define FC_SRQC_SZ 64
+#define FC_SRQE_SZ 32
+
+/* device capability */
+struct service_cap {
+ /* Host global resources */
+ u16 host_total_function;
+ u8 host_oq_id_mask_val;
+
+ /* DO NOT get interrupt_type from firmware */
+ enum intr_type interrupt_type;
+ u8 intr_chip_en;
+
+ u8 port_id; /* PF/VF's physical port */
+ u8 force_up;
+
+ u8 timer_en; /* 0:disable, 1:enable */
+
+ u16 max_sqs;
+ u16 max_rqs;
+
+ /* For test */
+ bool test_xid_alloc_mode;
+ bool test_gpa_check_enable;
+
+ u32 max_connect_num; /* PF/VF maximum connection number(1M) */
+ /* The maximum connections which can be stick to cache memory, max 1K */
+ u16 max_stick2cache_num;
+
+ struct nic_service_cap nic_cap; /* NIC capability */
+ struct fc_service_cap fc_cap; /* FC capability */
+};
+
+struct hifc_sync_time_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u64 mstime;
+};
+
+struct cfg_eq {
+ enum hifc_service_type type;
+ int eqn;
+ int free; /* 1 - alocated, 0- freed */
+};
+
+struct cfg_eq_info {
+ struct cfg_eq *eq;
+ u8 num_ceq;
+ u8 num_ceq_remain;
+ /* mutex used for allocate EQs */
+ struct mutex eq_mutex;
+};
+
+struct irq_alloc_info_st {
+ enum hifc_service_type type;
+ int free; /* 1 - alocated, 0- freed */
+ struct irq_info info;
+};
+
+struct cfg_irq_info {
+ struct irq_alloc_info_st *alloc_info;
+ u16 num_total;
+ u16 num_irq_remain;
+ u16 num_irq_hw; /* device max irq number */
+
+ /* mutex used for allocate EQs */
+ struct mutex irq_mutex;
+};
+
+#define VECTOR_THRESHOLD 2
+
+struct cfg_mgmt_info {
+ struct hifc_hwdev *hwdev;
+ struct service_cap svc_cap;
+ struct cfg_eq_info eq_info; /* EQ */
+ struct cfg_irq_info irq_param_info; /* IRQ */
+ u32 func_seq_num; /* temporary */
+};
+
+enum cfg_sub_cmd {
+ /* PPF(PF) <-> FW */
+ HIFC_CFG_NIC_CAP = 0,
+ CFG_FW_VERSION,
+ CFG_UCODE_VERSION,
+ HIFC_CFG_FUNC_CAP,
+ HIFC_CFG_MBOX_CAP = 6,
+};
+
+struct hifc_dev_cap {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ /* Public resource */
+ u8 sf_svc_attr;
+ u8 host_id;
+ u8 sf_en_pf;
+ u8 sf_en_vf;
+
+ u8 ep_id;
+ u8 intr_type;
+ u8 max_cos_id;
+ u8 er_id;
+ u8 port_id;
+ u8 max_vf;
+ u16 svc_cap_en;
+ u16 host_total_func;
+ u8 host_oq_id_mask_val;
+ u8 max_vf_cos_id;
+
+ u32 max_conn_num;
+ u16 max_stick2cache_num;
+ u16 max_bfilter_start_addr;
+ u16 bfilter_len;
+ u16 hash_bucket_num;
+ u8 cfg_file_ver;
+ u8 net_port_mode;
+ u8 valid_cos_bitmap; /* every bit indicate cos is valid */
+ u8 force_up;
+ u32 pf_num;
+ u32 pf_id_start;
+ u32 vf_num;
+ u32 vf_id_start;
+
+ /* shared resource */
+ u32 host_pctx_num;
+ u8 host_sf_en;
+ u8 rsvd2[3];
+ u32 host_ccxt_num;
+ u32 host_scq_num;
+ u32 host_srq_num;
+ u32 host_mpt_num;
+ /* l2nic */
+ u16 nic_max_sq;
+ u16 nic_max_rq;
+ u32 rsvd[46];
+ /* FC */
+ u32 fc_max_pctx;
+ u32 fc_max_scq;
+ u32 fc_max_srq;
+
+ u32 fc_max_cctx;
+ u32 fc_cctx_id_start;
+
+ u8 fc_vp_id_start;
+ u8 fc_vp_id_end;
+ u16 func_id;
+};
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_cmdq.c b/drivers/scsi/huawei/hifc/hifc_cmdq.c
new file mode 100644
index 000000000000..03531017c412
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cmdq.c
@@ -0,0 +1,1507 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_wq.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_eqs.h"
+#include "hifc_cmdq.h"
+
+#define CMDQ_CMD_TIMEOUT 1000 /* millisecond */
+#define UPPER_8_BITS(data) (((data) >> 8) & 0xFF)
+#define LOWER_8_BITS(data) ((data) & 0xFF)
+
+#define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0
+#define CMDQ_DB_INFO_QUEUE_TYPE_SHIFT 23
+#define CMDQ_DB_INFO_CMDQ_TYPE_SHIFT 24
+#define CMDQ_DB_INFO_SRC_TYPE_SHIFT 27
+#define CMDQ_DB_INFO_HI_PROD_IDX_MASK 0xFFU
+#define CMDQ_DB_INFO_QUEUE_TYPE_MASK 0x1U
+#define CMDQ_DB_INFO_CMDQ_TYPE_MASK 0x7U
+#define CMDQ_DB_INFO_SRC_TYPE_MASK 0x1FU
+
+#define CMDQ_DB_INFO_SET(val, member) \
+ (((val) & CMDQ_DB_INFO_##member##_MASK) << \
+ CMDQ_DB_INFO_##member##_SHIFT)
+
+#define CMDQ_CTRL_PI_SHIFT 0
+#define CMDQ_CTRL_CMD_SHIFT 16
+#define CMDQ_CTRL_MOD_SHIFT 24
+#define CMDQ_CTRL_ACK_TYPE_SHIFT 29
+#define CMDQ_CTRL_HW_BUSY_BIT_SHIFT 31
+#define CMDQ_CTRL_PI_MASK 0xFFFFU
+#define CMDQ_CTRL_CMD_MASK 0xFFU
+#define CMDQ_CTRL_MOD_MASK 0x1FU
+#define CMDQ_CTRL_ACK_TYPE_MASK 0x3U
+#define CMDQ_CTRL_HW_BUSY_BIT_MASK 0x1U
+
+#define CMDQ_CTRL_SET(val, member) \
+ (((val) & CMDQ_CTRL_##member##_MASK) \
+ << CMDQ_CTRL_##member##_SHIFT)
+
+#define CMDQ_CTRL_GET(val, member) \
+ (((val) >> CMDQ_CTRL_##member##_SHIFT) \
+ & CMDQ_CTRL_##member##_MASK)
+
+#define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT 0
+#define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT 15
+#define CMDQ_WQE_HEADER_DATA_FMT_SHIFT 22
+#define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT 23
+#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT 27
+#define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT 29
+#define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT 31
+
+#define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK 0xFFU
+#define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK 0x1U
+#define CMDQ_WQE_HEADER_DATA_FMT_MASK 0x1U
+#define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK 0x1U
+#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK 0x3U
+#define CMDQ_WQE_HEADER_CTRL_LEN_MASK 0x3U
+#define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK 0x1U
+
+#define CMDQ_WQE_HEADER_SET(val, member) \
+ (((val) & CMDQ_WQE_HEADER_##member##_MASK) \
+ << CMDQ_WQE_HEADER_##member##_SHIFT)
+
+#define CMDQ_WQE_HEADER_GET(val, member) \
+ (((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) \
+ & CMDQ_WQE_HEADER_##member##_MASK)
+
+#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0
+#define CMDQ_CTXT_EQ_ID_SHIFT 56
+#define CMDQ_CTXT_CEQ_ARM_SHIFT 61
+#define CMDQ_CTXT_CEQ_EN_SHIFT 62
+#define CMDQ_CTXT_HW_BUSY_BIT_SHIFT 63
+#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF
+#define CMDQ_CTXT_EQ_ID_MASK 0x1F
+#define CMDQ_CTXT_CEQ_ARM_MASK 0x1
+#define CMDQ_CTXT_CEQ_EN_MASK 0x1
+#define CMDQ_CTXT_HW_BUSY_BIT_MASK 0x1
+
+#define CMDQ_CTXT_PAGE_INFO_SET(val, member) \
+ (((u64)(val) & CMDQ_CTXT_##member##_MASK) \
+ << CMDQ_CTXT_##member##_SHIFT)
+
+#define CMDQ_CTXT_PAGE_INFO_GET(val, member) \
+ (((u64)(val) >> CMDQ_CTXT_##member##_SHIFT) \
+ & CMDQ_CTXT_##member##_MASK)
+
+#define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0
+#define CMDQ_CTXT_CI_SHIFT 52
+#define CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF
+#define CMDQ_CTXT_CI_MASK 0xFFF
+
+#define CMDQ_CTXT_BLOCK_INFO_SET(val, member) \
+ (((u64)(val) & CMDQ_CTXT_##member##_MASK) \
+ << CMDQ_CTXT_##member##_SHIFT)
+
+#define CMDQ_CTXT_BLOCK_INFO_GET(val, member) \
+ (((u64)(val) >> CMDQ_CTXT_##member##_SHIFT) \
+ & CMDQ_CTXT_##member##_MASK)
+
+#define SAVED_DATA_ARM_SHIFT 31
+#define SAVED_DATA_ARM_MASK 0x1U
+
+#define SAVED_DATA_SET(val, member) \
+ (((val) & SAVED_DATA_##member##_MASK) \
+ << SAVED_DATA_##member##_SHIFT)
+
+#define SAVED_DATA_CLEAR(val, member) \
+ ((val) & (~(SAVED_DATA_##member##_MASK \
+ << SAVED_DATA_##member##_SHIFT)))
+
+#define WQE_ERRCODE_VAL_SHIFT 20
+#define WQE_ERRCODE_VAL_MASK 0xF
+
+#define WQE_ERRCODE_GET(val, member) \
+ (((val) >> WQE_ERRCODE_##member##_SHIFT) & \
+ WQE_ERRCODE_##member##_MASK)
+
+#define CEQE_CMDQ_TYPE_SHIFT 0
+#define CEQE_CMDQ_TYPE_MASK 0x7
+
+#define CEQE_CMDQ_GET(val, member) \
+ (((val) >> CEQE_CMDQ_##member##_SHIFT) & CEQE_CMDQ_##member##_MASK)
+
+#define WQE_COMPLETED(ctrl_info) CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT)
+
+#define WQE_HEADER(wqe) ((struct hifc_cmdq_header *)(wqe))
+
+#define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3)
+
+#define CMDQ_DB_ADDR(db_base, pi) \
+ (((u8 *)(db_base) + HIFC_DB_OFF) + CMDQ_DB_PI_OFF(pi))
+
+#define CMDQ_PFN_SHIFT 12
+#define CMDQ_PFN(addr) ((addr) >> CMDQ_PFN_SHIFT)
+
+#define FIRST_DATA_TO_WRITE_LAST sizeof(u64)
+#define WQE_LCMD_SIZE 64
+#define WQE_SCMD_SIZE 64
+#define COMPLETE_LEN 3
+#define CMDQ_WQEBB_SIZE 64
+#define CMDQ_WQE_SIZE 64
+#define CMDQ_WQ_PAGE_SIZE 4096
+
+#define WQE_NUM_WQEBBS(wqe_size, wq) \
+ ((u16)(ALIGN((u32)(wqe_size), (wq)->wqebb_size) / (wq)->wqebb_size))
+
+#define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \
+ struct hifc_cmdqs, cmdq[0])
+
+#define CMDQ_SEND_CMPT_CODE 10
+#define CMDQ_COMPLETE_CMPT_CODE 11
+
+#define HIFC_GET_CMDQ_FREE_WQEBBS(cmdq_wq) \
+ atomic_read(&(cmdq_wq)->delta)
+
+enum cmdq_scmd_type {
+ CMDQ_SET_ARM_CMD = 2,
+};
+
+enum cmdq_wqe_type {
+ WQE_LCMD_TYPE,
+ WQE_SCMD_TYPE,
+};
+
+enum ctrl_sect_len {
+ CTRL_SECT_LEN = 1,
+ CTRL_DIRECT_SECT_LEN = 2,
+};
+
+enum bufdesc_len {
+ BUFDESC_LCMD_LEN = 2,
+ BUFDESC_SCMD_LEN = 3,
+};
+
+enum data_format {
+ DATA_SGE,
+ DATA_DIRECT,
+};
+
+enum completion_format {
+ COMPLETE_DIRECT,
+ COMPLETE_SGE,
+};
+
+enum completion_request {
+ CEQ_SET = 1,
+};
+
+enum cmdq_cmd_type {
+ SYNC_CMD_DIRECT_RESP,
+ SYNC_CMD_SGE_RESP,
+ ASYNC_CMD,
+};
+
+bool hifc_cmdq_idle(struct hifc_cmdq *cmdq)
+{
+ struct hifc_wq *wq = cmdq->wq;
+
+ return (atomic_read(&wq->delta) == wq->q_depth ? true : false);
+}
+
+struct hifc_cmd_buf *hifc_alloc_cmd_buf(void *hwdev)
+{
+ struct hifc_cmdqs *cmdqs;
+ struct hifc_cmd_buf *cmd_buf;
+ void *dev;
+
+ if (!hwdev) {
+ pr_err("Failed to alloc cmd buf, Invalid hwdev\n");
+ return NULL;
+ }
+
+ cmdqs = ((struct hifc_hwdev *)hwdev)->cmdqs;
+ dev = ((struct hifc_hwdev *)hwdev)->dev_hdl;
+
+ cmd_buf = kzalloc(sizeof(*cmd_buf), GFP_ATOMIC);
+ if (!cmd_buf)
+ return NULL;
+
+ cmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, GFP_ATOMIC,
+ &cmd_buf->dma_addr);
+ if (!cmd_buf->buf) {
+ sdk_err(dev, "Failed to allocate cmdq cmd buf from the pool\n");
+ goto alloc_pci_buf_err;
+ }
+
+ return cmd_buf;
+
+alloc_pci_buf_err:
+ kfree(cmd_buf);
+ return NULL;
+}
+
+void hifc_free_cmd_buf(void *hwdev, struct hifc_cmd_buf *cmd_buf)
+{
+ struct hifc_cmdqs *cmdqs;
+
+ if (!hwdev || !cmd_buf) {
+ pr_err("Failed to free cmd buf\n");
+ return;
+ }
+
+ cmdqs = ((struct hifc_hwdev *)hwdev)->cmdqs;
+
+ pci_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr);
+ kfree(cmd_buf);
+}
+
+static int cmdq_wqe_size(enum cmdq_wqe_type wqe_type)
+{
+ int wqe_size = 0;
+
+ switch (wqe_type) {
+ case WQE_LCMD_TYPE:
+ wqe_size = WQE_LCMD_SIZE;
+ break;
+ case WQE_SCMD_TYPE:
+ wqe_size = WQE_SCMD_SIZE;
+ break;
+ }
+
+ return wqe_size;
+}
+
+static int cmdq_get_wqe_size(enum bufdesc_len len)
+{
+ int wqe_size = 0;
+
+ switch (len) {
+ case BUFDESC_LCMD_LEN:
+ wqe_size = WQE_LCMD_SIZE;
+ break;
+ case BUFDESC_SCMD_LEN:
+ wqe_size = WQE_SCMD_SIZE;
+ break;
+ }
+
+ return wqe_size;
+}
+
+static void cmdq_set_completion(struct hifc_cmdq_completion *complete,
+ struct hifc_cmd_buf *buf_out)
+{
+ struct hifc_sge_resp *sge_resp = &complete->sge_resp;
+
+ hifc_set_sge(&sge_resp->sge, buf_out->dma_addr,
+ HIFC_CMDQ_BUF_SIZE);
+}
+
+static void cmdq_set_lcmd_bufdesc(struct hifc_cmdq_wqe_lcmd *wqe,
+ struct hifc_cmd_buf *buf_in)
+{
+ hifc_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size);
+}
+
+static void cmdq_set_inline_wqe_data(struct hifc_cmdq_inline_wqe *wqe,
+ const void *buf_in, u32 in_size)
+{
+ struct hifc_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd;
+
+ wqe_scmd->buf_desc.buf_len = in_size;
+ memcpy(wqe_scmd->buf_desc.data, buf_in, in_size);
+}
+
+static void cmdq_fill_db(struct hifc_cmdq_db *db,
+ enum hifc_cmdq_type cmdq_type, u16 prod_idx)
+{
+ db->db_info = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX) |
+ CMDQ_DB_INFO_SET(HIFC_DB_CMDQ_TYPE, QUEUE_TYPE) |
+ CMDQ_DB_INFO_SET(cmdq_type, CMDQ_TYPE) |
+ CMDQ_DB_INFO_SET(HIFC_DB_SRC_CMDQ_TYPE, SRC_TYPE);
+}
+
+static void cmdq_set_db(struct hifc_cmdq *cmdq,
+ enum hifc_cmdq_type cmdq_type, u16 prod_idx)
+{
+ struct hifc_cmdq_db db;
+
+ cmdq_fill_db(&db, cmdq_type, prod_idx);
+
+ /* The data that is written to HW should be in Big Endian Format */
+ db.db_info = cpu_to_be32(db.db_info);
+
+ wmb(); /* write all before the doorbell */
+ writel(db.db_info, CMDQ_DB_ADDR(cmdq->db_base, prod_idx));
+}
+
+static void cmdq_wqe_fill(void *dst, const void *src)
+{
+ memcpy((u8 *)dst + FIRST_DATA_TO_WRITE_LAST,
+ (u8 *)src + FIRST_DATA_TO_WRITE_LAST,
+ CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST);
+
+ wmb(); /* The first 8 bytes should be written last */
+
+ *(u64 *)dst = *(u64 *)src;
+}
+
+static void cmdq_prepare_wqe_ctrl(struct hifc_cmdq_wqe *wqe, int wrapped,
+ enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd, u16 prod_idx,
+ enum completion_format complete_format,
+ enum data_format data_format,
+ enum bufdesc_len buf_len)
+{
+ struct hifc_ctrl *ctrl;
+ enum ctrl_sect_len ctrl_len;
+ struct hifc_cmdq_wqe_lcmd *wqe_lcmd;
+ struct hifc_cmdq_wqe_scmd *wqe_scmd;
+ u32 saved_data = WQE_HEADER(wqe)->saved_data;
+
+ if (data_format == DATA_SGE) {
+ wqe_lcmd = &wqe->wqe_lcmd;
+
+ wqe_lcmd->status.status_info = 0;
+ ctrl = &wqe_lcmd->ctrl;
+ ctrl_len = CTRL_SECT_LEN;
+ } else {
+ wqe_scmd = &wqe->inline_wqe.wqe_scmd;
+
+ wqe_scmd->status.status_info = 0;
+ ctrl = &wqe_scmd->ctrl;
+ ctrl_len = CTRL_DIRECT_SECT_LEN;
+ }
+
+ ctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI) |
+ CMDQ_CTRL_SET(cmd, CMD) |
+ CMDQ_CTRL_SET(mod, MOD) |
+ CMDQ_CTRL_SET(ack_type, ACK_TYPE);
+
+ WQE_HEADER(wqe)->header_info =
+ CMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) |
+ CMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) |
+ CMDQ_WQE_HEADER_SET(data_format, DATA_FMT) |
+ CMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ) |
+ CMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) |
+ CMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN) |
+ CMDQ_WQE_HEADER_SET((u32)wrapped, HW_BUSY_BIT);
+
+ if (cmd == CMDQ_SET_ARM_CMD && mod == HIFC_MOD_COMM) {
+ saved_data &= SAVED_DATA_CLEAR(saved_data, ARM);
+ WQE_HEADER(wqe)->saved_data = saved_data |
+ SAVED_DATA_SET(1, ARM);
+ } else {
+ saved_data &= SAVED_DATA_CLEAR(saved_data, ARM);
+ WQE_HEADER(wqe)->saved_data = saved_data;
+ }
+}
+
+static void cmdq_set_lcmd_wqe(struct hifc_cmdq_wqe *wqe,
+ enum cmdq_cmd_type cmd_type,
+ struct hifc_cmd_buf *buf_in,
+ struct hifc_cmd_buf *buf_out, int wrapped,
+ enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd, u16 prod_idx)
+{
+ struct hifc_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd;
+ enum completion_format complete_format = COMPLETE_DIRECT;
+
+ switch (cmd_type) {
+ case SYNC_CMD_SGE_RESP:
+ if (buf_out) {
+ complete_format = COMPLETE_SGE;
+ cmdq_set_completion(&wqe_lcmd->completion, buf_out);
+ }
+ break;
+ case SYNC_CMD_DIRECT_RESP:
+ complete_format = COMPLETE_DIRECT;
+ wqe_lcmd->completion.direct_resp = 0;
+ break;
+ case ASYNC_CMD:
+ complete_format = COMPLETE_DIRECT;
+ wqe_lcmd->completion.direct_resp = 0;
+
+ wqe_lcmd->buf_desc.saved_async_buf = (u64)(buf_in);
+ break;
+ }
+
+ cmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd,
+ prod_idx, complete_format, DATA_SGE,
+ BUFDESC_LCMD_LEN);
+
+ cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);
+}
+
+static void cmdq_set_inline_wqe(struct hifc_cmdq_wqe *wqe,
+ enum cmdq_cmd_type cmd_type,
+ void *buf_in, u16 in_size,
+ struct hifc_cmd_buf *buf_out, int wrapped,
+ enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd, u16 prod_idx)
+{
+ struct hifc_cmdq_wqe_scmd *wqe_scmd = &wqe->inline_wqe.wqe_scmd;
+ enum completion_format complete_format = COMPLETE_DIRECT;
+
+ switch (cmd_type) {
+ case SYNC_CMD_SGE_RESP:
+ complete_format = COMPLETE_SGE;
+ cmdq_set_completion(&wqe_scmd->completion, buf_out);
+ break;
+ case SYNC_CMD_DIRECT_RESP:
+ complete_format = COMPLETE_DIRECT;
+ wqe_scmd->completion.direct_resp = 0;
+ break;
+ default:
+ break;
+ }
+
+ cmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd, prod_idx,
+ complete_format, DATA_DIRECT, BUFDESC_SCMD_LEN);
+
+ cmdq_set_inline_wqe_data(&wqe->inline_wqe, buf_in, in_size);
+}
+
+static void cmdq_update_cmd_status(struct hifc_cmdq *cmdq, u16 prod_idx,
+ struct hifc_cmdq_wqe *wqe)
+{
+ struct hifc_cmdq_cmd_info *cmd_info;
+ struct hifc_cmdq_wqe_lcmd *wqe_lcmd;
+ u32 status_info;
+
+ wqe_lcmd = &wqe->wqe_lcmd;
+ cmd_info = &cmdq->cmd_infos[prod_idx];
+
+ if (cmd_info->errcode) {
+ status_info = be32_to_cpu(wqe_lcmd->status.status_info);
+ *cmd_info->errcode = WQE_ERRCODE_GET(status_info, VAL);
+ }
+
+ if (cmd_info->direct_resp &&
+ cmd_info->cmd_type == HIFC_CMD_TYPE_DIRECT_RESP)
+ *cmd_info->direct_resp =
+ cpu_to_be64(wqe_lcmd->completion.direct_resp);
+}
+
+static int hifc_cmdq_sync_timeout_check(struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_wqe *wqe, u16 pi,
+ enum hifc_mod_type mod, u8 cmd)
+{
+ struct hifc_cmdq_wqe_lcmd *wqe_lcmd;
+ struct hifc_ctrl *ctrl;
+ u32 ctrl_info;
+
+ wqe_lcmd = &wqe->wqe_lcmd;
+ ctrl = &wqe_lcmd->ctrl;
+ ctrl_info = be32_to_cpu((ctrl)->ctrl_info);
+ if (!WQE_COMPLETED(ctrl_info)) {
+ sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command check busy bit not set, mod: %u, cmd: 0x%x\n",
+ mod, cmd);
+ return -EFAULT;
+ }
+
+ cmdq_update_cmd_status(cmdq, pi, wqe);
+
+ sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command check succeed, mod: %u, cmd: 0x%x\n",
+ mod, cmd);
+ return 0;
+}
+
+static void __clear_cmd_info(struct hifc_cmdq_cmd_info *cmd_info,
+ struct hifc_cmdq_cmd_info *saved_cmd_info)
+{
+ if (cmd_info->errcode == saved_cmd_info->errcode)
+ cmd_info->errcode = NULL;
+
+ if (cmd_info->done == saved_cmd_info->done)
+ cmd_info->done = NULL;
+
+ if (cmd_info->direct_resp == saved_cmd_info->direct_resp)
+ cmd_info->direct_resp = NULL;
+}
+
+static int
+cmdq_sync_cmd_timeout_handler(struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_cmd_info *cmd_info,
+ struct hifc_cmdq_cmd_info *saved_cmd_info,
+ struct hifc_cmdq_wqe *curr_wqe,
+ enum hifc_mod_type mod, u8 cmd,
+ u16 curr_prod_idx, u64 curr_msg_id)
+{
+ int err;
+
+ spin_lock_bh(&cmdq->cmdq_lock);
+
+ if (cmd_info->cmpt_code == saved_cmd_info->cmpt_code)
+ cmd_info->cmpt_code = NULL;
+
+ if (*saved_cmd_info->cmpt_code == CMDQ_COMPLETE_CMPT_CODE) {
+ sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command (mod: %u, cmd: 0x%x)has been completed\n",
+ mod, cmd);
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ return 0;
+ }
+
+ if (curr_msg_id == cmd_info->cmdq_msg_id) {
+ err = hifc_cmdq_sync_timeout_check(cmdq, curr_wqe,
+ curr_prod_idx,
+ mod, cmd);
+ if (err)
+ cmd_info->cmd_type = HIFC_CMD_TYPE_TIMEOUT;
+ else
+ cmd_info->cmd_type = HIFC_CMD_TYPE_FAKE_TIMEOUT;
+ } else {
+ err = -ETIMEDOUT;
+ sdk_err(cmdq->hwdev->dev_hdl,
+ "Cmdq sync command current msg id dismatch with cmd_info msg id, mod: %u, cmd: 0x%x\n",
+ mod, cmd);
+ }
+
+ __clear_cmd_info(cmd_info, saved_cmd_info);
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+
+ return err;
+}
+
+static int cmdq_sync_cmd_direct_resp(struct hifc_cmdq *cmdq,
+ enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in,
+ u64 *out_param, u32 timeout)
+{
+ struct hifc_wq *wq = cmdq->wq;
+ struct hifc_cmdq_wqe *curr_wqe, wqe;
+ struct hifc_cmdq_cmd_info *cmd_info, saved_cmd_info;
+ struct completion done;
+ u16 curr_prod_idx, next_prod_idx, num_wqebbs;
+ int wrapped, errcode = 0, wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
+ int cmpt_code = CMDQ_SEND_CMPT_CODE;
+ ulong timeo;
+ u64 curr_msg_id;
+ int err;
+
+ num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
+
+ /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */
+ spin_lock_bh(&cmdq->cmdq_lock);
+
+ /* in order to save a wqebb for setting arm_bit when
+ * send cmdq commands frequently resulting in cmdq full
+ */
+ if (HIFC_GET_CMDQ_FREE_WQEBBS(wq) < num_wqebbs + 1) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ return -EBUSY;
+ }
+
+ /* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow */
+ curr_wqe = hifc_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
+ if (!curr_wqe) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ sdk_err(cmdq->hwdev->dev_hdl, "Can not get avalible wqebb, mod: %u, cmd: 0x%x\n",
+ mod, cmd);
+ return -EBUSY;
+ }
+
+ memset(&wqe, 0, sizeof(wqe));
+
+ wrapped = cmdq->wrapped;
+
+ next_prod_idx = curr_prod_idx + num_wqebbs;
+ if (next_prod_idx >= wq->q_depth) {
+ cmdq->wrapped = !cmdq->wrapped;
+ next_prod_idx -= wq->q_depth;
+ }
+
+ cmd_info = &cmdq->cmd_infos[curr_prod_idx];
+
+ init_completion(&done);
+
+ cmd_info->done = &done;
+ cmd_info->errcode = &errcode;
+ cmd_info->direct_resp = out_param;
+ cmd_info->cmpt_code = &cmpt_code;
+
+ memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info));
+
+ cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL,
+ wrapped, ack_type, mod, cmd, curr_prod_idx);
+
+ /* The data that is written to HW should be in Big Endian Format */
+ hifc_cpu_to_be32(&wqe, wqe_size);
+
+ /* CMDQ WQE is not shadow, therefore wqe will be written to wq */
+ cmdq_wqe_fill(curr_wqe, &wqe);
+
+ cmd_info->cmd_type = HIFC_CMD_TYPE_DIRECT_RESP;
+
+ (cmd_info->cmdq_msg_id)++;
+ curr_msg_id = cmd_info->cmdq_msg_id;
+
+ cmdq_set_db(cmdq, HIFC_CMDQ_SYNC, next_prod_idx);
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+
+ timeo = msecs_to_jiffies(timeout ? timeout : CMDQ_CMD_TIMEOUT);
+ if (!wait_for_completion_timeout(&done, timeo)) {
+ err = cmdq_sync_cmd_timeout_handler(cmdq, cmd_info,
+ &saved_cmd_info,
+ curr_wqe, mod, cmd,
+ curr_prod_idx, curr_msg_id);
+
+ if (!err)
+ goto timeout_check_ok;
+
+ sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command timeout, prod idx: 0x%x\n",
+ curr_prod_idx);
+ return -ETIMEDOUT;
+ }
+
+timeout_check_ok:
+ smp_rmb(); /* read error code after completion */
+
+ if (errcode > 1)
+ return errcode;
+
+ return 0;
+}
+
+static int cmdq_sync_cmd_detail_resp(struct hifc_cmdq *cmdq,
+ enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in,
+ struct hifc_cmd_buf *buf_out,
+ u32 timeout)
+{
+ struct hifc_wq *wq = cmdq->wq;
+ struct hifc_cmdq_wqe *curr_wqe, wqe;
+ struct hifc_cmdq_cmd_info *cmd_info, saved_cmd_info;
+ struct completion done;
+ u16 curr_prod_idx, next_prod_idx, num_wqebbs;
+ int wrapped, errcode = 0, wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
+ int cmpt_code = CMDQ_SEND_CMPT_CODE;
+ ulong timeo;
+ u64 curr_msg_id;
+ int err;
+
+ num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
+
+ /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */
+ spin_lock_bh(&cmdq->cmdq_lock);
+
+ /* in order to save a wqebb for setting arm_bit when
+ * send cmdq commands frequently resulting in cmdq full
+ */
+ if (HIFC_GET_CMDQ_FREE_WQEBBS(wq) < num_wqebbs + 1) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ return -EBUSY;
+ }
+
+ /* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow*/
+ curr_wqe = hifc_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
+ if (!curr_wqe) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ sdk_err(cmdq->hwdev->dev_hdl, "Can not get avalible wqebb, mod: %u, cmd: 0x%x\n",
+ mod, cmd);
+ return -EBUSY;
+ }
+
+ memset(&wqe, 0, sizeof(wqe));
+
+ wrapped = cmdq->wrapped;
+
+ next_prod_idx = curr_prod_idx + num_wqebbs;
+ if (next_prod_idx >= wq->q_depth) {
+ cmdq->wrapped = !cmdq->wrapped;
+ next_prod_idx -= wq->q_depth;
+ }
+
+ cmd_info = &cmdq->cmd_infos[curr_prod_idx];
+
+ init_completion(&done);
+
+ cmd_info->done = &done;
+ cmd_info->errcode = &errcode;
+ cmd_info->cmpt_code = &cmpt_code;
+
+ memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info));
+
+ cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_SGE_RESP, buf_in, buf_out,
+ wrapped, ack_type, mod, cmd, curr_prod_idx);
+
+ hifc_cpu_to_be32(&wqe, wqe_size);
+
+ cmdq_wqe_fill(curr_wqe, &wqe);
+
+ cmd_info->cmd_type = HIFC_CMD_TYPE_SGE_RESP;
+
+ (cmd_info->cmdq_msg_id)++;
+ curr_msg_id = cmd_info->cmdq_msg_id;
+
+ cmdq_set_db(cmdq, HIFC_CMDQ_SYNC, next_prod_idx);
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+
+ timeo = msecs_to_jiffies(timeout ? timeout : CMDQ_CMD_TIMEOUT);
+ if (!wait_for_completion_timeout(&done, timeo)) {
+ err = cmdq_sync_cmd_timeout_handler(cmdq, cmd_info,
+ &saved_cmd_info,
+ curr_wqe, mod, cmd,
+ curr_prod_idx, curr_msg_id);
+ if (!err)
+ goto timeout_check_ok;
+
+ sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command timeout, prod idx: 0x%x\n",
+ curr_prod_idx);
+ return -ETIMEDOUT;
+ }
+
+timeout_check_ok:
+
+ smp_rmb(); /* read error code after completion */
+
+ if (errcode > 1)
+ return errcode;
+
+ return 0;
+}
+
+static int cmdq_async_cmd(struct hifc_cmdq *cmdq, enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in)
+{
+ struct hifc_wq *wq = cmdq->wq;
+ int wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
+ u16 curr_prod_idx, next_prod_idx, num_wqebbs;
+ struct hifc_cmdq_wqe *curr_wqe, wqe;
+ int wrapped;
+
+ num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
+
+ spin_lock_bh(&cmdq->cmdq_lock);
+
+ /* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow*/
+ curr_wqe = hifc_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
+ if (!curr_wqe) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ return -EBUSY;
+ }
+
+ memset(&wqe, 0, sizeof(wqe));
+
+ wrapped = cmdq->wrapped;
+ next_prod_idx = curr_prod_idx + num_wqebbs;
+ if (next_prod_idx >= cmdq->wq->q_depth) {
+ cmdq->wrapped = !cmdq->wrapped;
+ next_prod_idx -= cmdq->wq->q_depth;
+ }
+
+ cmdq_set_lcmd_wqe(&wqe, ASYNC_CMD, buf_in, NULL, wrapped,
+ ack_type, mod, cmd, curr_prod_idx);
+
+ /* The data that is written to HW should be in Big Endian Format */
+ hifc_cpu_to_be32(&wqe, wqe_size);
+
+ cmdq_wqe_fill(curr_wqe, &wqe);
+
+ cmdq->cmd_infos[curr_prod_idx].cmd_type = HIFC_CMD_TYPE_ASYNC;
+
+ cmdq_set_db(cmdq, HIFC_CMDQ_ASYNC, next_prod_idx);
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+
+ return 0;
+}
+
+static int cmdq_set_arm_bit(struct hifc_cmdq *cmdq, void *buf_in, u16 in_size)
+{
+ struct hifc_wq *wq = cmdq->wq;
+ struct hifc_cmdq_wqe *curr_wqe, wqe;
+ u16 curr_prod_idx, next_prod_idx, num_wqebbs;
+ int wrapped, wqe_size = cmdq_wqe_size(WQE_SCMD_TYPE);
+
+ num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
+
+ /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */
+ spin_lock_bh(&cmdq->cmdq_lock);
+
+ /* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow*/
+ curr_wqe = hifc_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
+ if (!curr_wqe) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ sdk_err(cmdq->hwdev->dev_hdl, "Can not get avalible wqebb setting arm\n");
+ return -EBUSY;
+ }
+
+ memset(&wqe, 0, sizeof(wqe));
+
+ wrapped = cmdq->wrapped;
+
+ next_prod_idx = curr_prod_idx + num_wqebbs;
+ if (next_prod_idx >= wq->q_depth) {
+ cmdq->wrapped = !cmdq->wrapped;
+ next_prod_idx -= wq->q_depth;
+ }
+
+ cmdq_set_inline_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, in_size, NULL,
+ wrapped, HIFC_ACK_TYPE_CMDQ, HIFC_MOD_COMM,
+ CMDQ_SET_ARM_CMD, curr_prod_idx);
+
+ /* The data that is written to HW should be in Big Endian Format */
+ hifc_cpu_to_be32(&wqe, wqe_size);
+
+ /* cmdq wqe is not shadow, therefore wqe will be written to wq */
+ cmdq_wqe_fill(curr_wqe, &wqe);
+
+ cmdq->cmd_infos[curr_prod_idx].cmd_type = HIFC_CMD_TYPE_SET_ARM;
+
+ cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx);
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+
+ return 0;
+}
+
+static int cmdq_params_valid(void *hwdev, struct hifc_cmd_buf *buf_in)
+{
+ if (!buf_in || !hwdev) {
+ pr_err("Invalid CMDQ buffer addr\n");
+ return -EINVAL;
+ }
+
+ if (!buf_in->size || buf_in->size > HIFC_CMDQ_MAX_DATA_SIZE) {
+ pr_err("Invalid CMDQ buffer size: 0x%x\n", buf_in->size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define WAIT_CMDQ_ENABLE_TIMEOUT 300
+
+static int wait_cmdqs_enable(struct hifc_cmdqs *cmdqs)
+{
+ unsigned long end;
+
+ end = jiffies + msecs_to_jiffies(WAIT_CMDQ_ENABLE_TIMEOUT);
+ do {
+ if (cmdqs->status & HIFC_CMDQ_ENABLE)
+ return 0;
+ } while (time_before(jiffies, end) && cmdqs->hwdev->chip_present_flag &&
+ !cmdqs->disable_flag);
+
+ cmdqs->disable_flag = 1;
+
+ return -EBUSY;
+}
+
+int hifc_cmdq_direct_resp(void *hwdev, enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in, u64 *out_param,
+ u32 timeout)
+{
+ struct hifc_cmdqs *cmdqs;
+ int err = cmdq_params_valid(hwdev, buf_in);
+
+ if (err) {
+ pr_err("Invalid CMDQ parameters\n");
+ return err;
+ }
+
+ cmdqs = ((struct hifc_hwdev *)hwdev)->cmdqs;
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag) ||
+ !hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_CMDQ_INITED))
+ return -EPERM;
+
+ err = wait_cmdqs_enable(cmdqs);
+ if (err) {
+ sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n");
+ return err;
+ }
+
+ err = cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HIFC_CMDQ_SYNC], ack_type,
+ mod, cmd, buf_in, out_param, timeout);
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag))
+ return -ETIMEDOUT;
+ else
+ return err;
+}
+
+int hifc_cmdq_detail_resp(void *hwdev,
+ enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in,
+ struct hifc_cmd_buf *buf_out,
+ u32 timeout)
+{
+ struct hifc_cmdqs *cmdqs;
+ int err = cmdq_params_valid(hwdev, buf_in);
+
+ if (err)
+ return err;
+
+ cmdqs = ((struct hifc_hwdev *)hwdev)->cmdqs;
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag) ||
+ !hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_CMDQ_INITED))
+ return -EPERM;
+
+ err = wait_cmdqs_enable(cmdqs);
+ if (err) {
+ sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n");
+ return err;
+ }
+
+ err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[HIFC_CMDQ_SYNC], ack_type,
+ mod, cmd, buf_in, buf_out, timeout);
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag))
+ return -ETIMEDOUT;
+ else
+ return err;
+}
+
+int hifc_cmdq_async(void *hwdev, enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in)
+{
+ struct hifc_cmdqs *cmdqs;
+ int err = cmdq_params_valid(hwdev, buf_in);
+
+ if (err)
+ return err;
+
+ cmdqs = ((struct hifc_hwdev *)hwdev)->cmdqs;
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag) ||
+ !hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_CMDQ_INITED))
+ return -EPERM;
+
+ err = wait_cmdqs_enable(cmdqs);
+ if (err) {
+ sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n");
+ return err;
+ }
+
+ return cmdq_async_cmd(&cmdqs->cmdq[HIFC_CMDQ_ASYNC], ack_type, mod,
+ cmd, buf_in);
+}
+
+int hifc_set_arm_bit(void *hwdev, enum hifc_set_arm_type q_type, u16 q_id)
+{
+ struct hifc_cmdqs *cmdqs;
+ struct hifc_cmdq *cmdq;
+ struct hifc_cmdq_arm_bit arm_bit;
+ enum hifc_cmdq_type cmdq_type = HIFC_CMDQ_SYNC;
+ u16 in_size;
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag) ||
+ !hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_CMDQ_INITED))
+ return -EPERM;
+
+ cmdqs = ((struct hifc_hwdev *)hwdev)->cmdqs;
+
+ if (!(cmdqs->status & HIFC_CMDQ_ENABLE))
+ return -EBUSY;
+
+ if (q_type == HIFC_SET_ARM_CMDQ) {
+ if (q_id >= HIFC_MAX_CMDQ_TYPES)
+ return -EFAULT;
+
+ cmdq_type = q_id;
+ }
+ /* sq is using interrupt now, so we only need to set arm bit for cmdq,
+ * remove comment below if need to set sq arm bit
+ * else
+ * cmdq_type = HIFC_CMDQ_SYNC;
+ */
+
+ cmdq = &cmdqs->cmdq[cmdq_type];
+
+ arm_bit.q_type = q_type;
+ arm_bit.q_id = q_id;
+ in_size = sizeof(arm_bit);
+
+ err = cmdq_set_arm_bit(cmdq, &arm_bit, in_size);
+ if (err) {
+ sdk_err(cmdqs->hwdev->dev_hdl,
+ "Failed to set arm for q_type: %d, qid %d\n",
+ q_type, q_id);
+ return err;
+ }
+
+ return 0;
+}
+
+static void clear_wqe_complete_bit(struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_wqe *wqe, u16 ci)
+{
+ struct hifc_cmdq_wqe_lcmd *wqe_lcmd;
+ struct hifc_cmdq_inline_wqe *inline_wqe;
+ struct hifc_cmdq_wqe_scmd *wqe_scmd;
+ struct hifc_ctrl *ctrl;
+ u32 header_info = be32_to_cpu(WQE_HEADER(wqe)->header_info);
+ int buf_len = CMDQ_WQE_HEADER_GET(header_info, BUFDESC_LEN);
+ int wqe_size = cmdq_get_wqe_size(buf_len);
+ u16 num_wqebbs;
+
+ if (wqe_size == WQE_LCMD_SIZE) {
+ wqe_lcmd = &wqe->wqe_lcmd;
+ ctrl = &wqe_lcmd->ctrl;
+ } else {
+ inline_wqe = &wqe->inline_wqe;
+ wqe_scmd = &inline_wqe->wqe_scmd;
+ ctrl = &wqe_scmd->ctrl;
+ }
+
+ /* clear HW busy bit */
+ ctrl->ctrl_info = 0;
+ cmdq->cmd_infos[ci].cmd_type = HIFC_CMD_TYPE_NONE;
+
+ wmb(); /* verify wqe is clear */
+
+ num_wqebbs = WQE_NUM_WQEBBS(wqe_size, cmdq->wq);
+ hifc_put_wqe(cmdq->wq, num_wqebbs);
+}
+
+static void cmdq_sync_cmd_handler(struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_wqe *wqe, u16 cons_idx)
+{
+ u16 prod_idx = cons_idx;
+
+ spin_lock(&cmdq->cmdq_lock);
+
+ cmdq_update_cmd_status(cmdq, prod_idx, wqe);
+
+ if (cmdq->cmd_infos[prod_idx].cmpt_code) {
+ *cmdq->cmd_infos[prod_idx].cmpt_code =
+ CMDQ_COMPLETE_CMPT_CODE;
+ cmdq->cmd_infos[prod_idx].cmpt_code = NULL;
+ }
+
+ /* make sure cmpt_code operation before done operation */
+ smp_rmb();
+
+ if (cmdq->cmd_infos[prod_idx].done) {
+ complete(cmdq->cmd_infos[prod_idx].done);
+ cmdq->cmd_infos[prod_idx].done = NULL;
+ }
+
+ spin_unlock(&cmdq->cmdq_lock);
+
+ clear_wqe_complete_bit(cmdq, wqe, cons_idx);
+}
+
+static void cmdq_async_cmd_handler(struct hifc_hwdev *hwdev,
+ struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_wqe *wqe, u16 ci)
+{
+ u64 buf = wqe->wqe_lcmd.buf_desc.saved_async_buf;
+ int addr_sz = sizeof(u64);
+
+ hifc_be32_to_cpu((void *)&buf, addr_sz);
+ if (buf)
+ hifc_free_cmd_buf(hwdev, (struct hifc_cmd_buf *)buf);
+
+ clear_wqe_complete_bit(cmdq, wqe, ci);
+}
+
+static int cmdq_arm_ceq_handler(struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_wqe *wqe, u16 ci)
+{
+ struct hifc_cmdq_inline_wqe *inline_wqe = &wqe->inline_wqe;
+ struct hifc_cmdq_wqe_scmd *wqe_scmd = &inline_wqe->wqe_scmd;
+ struct hifc_ctrl *ctrl = &wqe_scmd->ctrl;
+ u32 ctrl_info = be32_to_cpu((ctrl)->ctrl_info);
+
+ if (!WQE_COMPLETED(ctrl_info))
+ return -EBUSY;
+
+ clear_wqe_complete_bit(cmdq, wqe, ci);
+
+ return 0;
+}
+
+#define HIFC_CMDQ_WQE_HEAD_LEN 32
+static void hifc_dump_cmdq_wqe_head(struct hifc_hwdev *hwdev,
+ struct hifc_cmdq_wqe *wqe)
+{
+ u32 i;
+ u32 *data = (u32 *)wqe;
+
+ for (i = 0; i < (HIFC_CMDQ_WQE_HEAD_LEN / sizeof(u32)); i += 4) {
+ sdk_info(hwdev->dev_hdl, "wqe data: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ data[i], data[i + 1], data[i + 2],
+ data[i + 3]);/*lint !e679*/
+ }
+}
+
+#define CMDQ_CMD_TYPE_TIMEOUT(cmd_type) \
+ ((cmd_type) == HIFC_CMD_TYPE_TIMEOUT || \
+ (cmd_type) == HIFC_CMD_TYPE_FAKE_TIMEOUT)
+
+static inline void cmdq_response_handle(struct hifc_hwdev *hwdev,
+ struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_wqe *wqe,
+ enum hifc_cmdq_type cmdq_type, u16 ci)
+{
+ if (cmdq_type == HIFC_CMDQ_ASYNC)
+ cmdq_async_cmd_handler(hwdev, cmdq, wqe, ci);
+ else
+ cmdq_sync_cmd_handler(cmdq, wqe, ci);
+}
+
+static inline void set_arm_bit(struct hifc_hwdev *hwdev, int set_arm,
+ enum hifc_cmdq_type cmdq_type)
+{
+ if (set_arm)
+ hifc_set_arm_bit(hwdev, HIFC_SET_ARM_CMDQ, cmdq_type);
+}
+
+void hifc_cmdq_ceq_handler(void *handle, u32 ceqe_data)
+{
+ struct hifc_cmdqs *cmdqs = ((struct hifc_hwdev *)handle)->cmdqs;
+ enum hifc_cmdq_type cmdq_type = CEQE_CMDQ_GET(ceqe_data, TYPE);
+ struct hifc_cmdq *cmdq = &cmdqs->cmdq[cmdq_type];
+ struct hifc_hwdev *hwdev = cmdqs->hwdev;
+ struct hifc_cmdq_wqe *wqe;
+ struct hifc_cmdq_wqe_lcmd *wqe_lcmd;
+ struct hifc_ctrl *ctrl;
+ struct hifc_cmdq_cmd_info *cmd_info;
+ u32 ctrl_info;
+ u16 ci;
+ int set_arm = 1;
+
+ while ((wqe = hifc_read_wqe(cmdq->wq, 1, &ci)) != NULL) {
+ cmd_info = &cmdq->cmd_infos[ci];
+
+ if (cmd_info->cmd_type == HIFC_CMD_TYPE_NONE) {
+ set_arm = 1;
+ break;
+ } else if (CMDQ_CMD_TYPE_TIMEOUT(cmd_info->cmd_type)) {
+ if (cmd_info->cmd_type == HIFC_CMD_TYPE_TIMEOUT) {
+ sdk_info(hwdev->dev_hdl, "Cmdq timeout, q_id: %u, ci: %u\n",
+ cmdq_type, ci);
+ hifc_dump_cmdq_wqe_head(hwdev, wqe);
+ }
+
+ set_arm = 1;
+ clear_wqe_complete_bit(cmdq, wqe, ci);
+ } else if (cmd_info->cmd_type == HIFC_CMD_TYPE_SET_ARM) {
+ /* arm_bit was set until here */
+ set_arm = 0;
+
+ if (cmdq_arm_ceq_handler(cmdq, wqe, ci))
+ break;
+ } else {
+ set_arm = 1;
+
+ /* only arm bit is using scmd wqe, the wqe is lcmd */
+ wqe_lcmd = &wqe->wqe_lcmd;
+ ctrl = &wqe_lcmd->ctrl;
+ ctrl_info = be32_to_cpu((ctrl)->ctrl_info);
+
+ if (!WQE_COMPLETED(ctrl_info))
+ break;
+
+ /* This memory barrier is needed to keep us from reading
+ * any other fields out of the cmdq wqe until we have
+ * verified the command has been processed and
+ * written back.
+ */
+ dma_rmb();
+
+ cmdq_response_handle(hwdev, cmdq, wqe, cmdq_type, ci);
+ }
+ }
+
+ set_arm_bit(hwdev, set_arm, cmdq_type);
+}
+
+static void cmdq_init_queue_ctxt(struct hifc_cmdq *cmdq,
+ struct hifc_cmdq_pages *cmdq_pages,
+ struct hifc_cmdq_ctxt *cmdq_ctxt)
+{
+ struct hifc_cmdqs *cmdqs = cmdq_to_cmdqs(cmdq);
+ struct hifc_hwdev *hwdev = cmdqs->hwdev;
+ struct hifc_wq *wq = cmdq->wq;
+ struct hifc_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;
+ u64 wq_first_page_paddr, cmdq_first_block_paddr, pfn;
+ u16 start_ci = (u16)wq->cons_idx;
+
+ /* The data in the HW is in Big Endian Format */
+ wq_first_page_paddr = be64_to_cpu(*wq->block_vaddr);
+
+ pfn = CMDQ_PFN(wq_first_page_paddr);
+
+ ctxt_info->curr_wqe_page_pfn =
+ CMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) |
+ CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN) |
+ CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_ARM) |
+ CMDQ_CTXT_PAGE_INFO_SET(HIFC_CEQ_ID_CMDQ, EQ_ID) |
+ CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN);
+
+ /* If only use one page, use 0-level CLA */
+ if (cmdq->wq->num_q_pages != 1) {
+ cmdq_first_block_paddr = cmdq_pages->cmdq_page_paddr;
+ pfn = CMDQ_PFN(cmdq_first_block_paddr);
+ }
+
+ ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) |
+ CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN);
+
+ cmdq_ctxt->func_idx = hifc_global_func_id_hw(hwdev);
+ cmdq_ctxt->ppf_idx = HIFC_HWIF_PPF_IDX(hwdev->hwif);
+ cmdq_ctxt->cmdq_id = cmdq->cmdq_type;
+}
+
+static int init_cmdq(struct hifc_cmdq *cmdq, struct hifc_hwdev *hwdev,
+ struct hifc_wq *wq, enum hifc_cmdq_type q_type)
+{
+ void __iomem *db_base;
+ int err = 0;
+
+ cmdq->wq = wq;
+ cmdq->cmdq_type = q_type;
+ cmdq->wrapped = 1;
+ cmdq->hwdev = hwdev;
+
+ spin_lock_init(&cmdq->cmdq_lock);
+
+ cmdq->cmd_infos = kcalloc(wq->q_depth, sizeof(*cmdq->cmd_infos),
+ GFP_KERNEL);
+ if (!cmdq->cmd_infos) {
+ err = -ENOMEM;
+ goto cmd_infos_err;
+ }
+
+ err = hifc_alloc_db_addr(hwdev, &db_base, NULL);
+ if (err)
+ goto alloc_db_err;
+
+ cmdq->db_base = (u8 *)db_base;
+ return 0;
+
+alloc_db_err:
+ kfree(cmdq->cmd_infos);
+
+cmd_infos_err:
+
+ return err;
+}
+
+static void free_cmdq(struct hifc_hwdev *hwdev, struct hifc_cmdq *cmdq)
+{
+ hifc_free_db_addr(hwdev, cmdq->db_base, NULL);
+ kfree(cmdq->cmd_infos);
+}
+
+int hifc_set_cmdq_ctxts(struct hifc_hwdev *hwdev)
+{
+ struct hifc_cmdqs *cmdqs = hwdev->cmdqs;
+ struct hifc_cmdq_ctxt *cmdq_ctxt, cmdq_ctxt_out = {0};
+ enum hifc_cmdq_type cmdq_type;
+ u16 in_size;
+ u16 out_size = sizeof(*cmdq_ctxt);
+ int err;
+
+ cmdq_type = HIFC_CMDQ_SYNC;
+ for (; cmdq_type < HIFC_MAX_CMDQ_TYPES; cmdq_type++) {
+ cmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;
+ cmdq_ctxt->func_idx = hifc_global_func_id_hw(hwdev);
+ in_size = sizeof(*cmdq_ctxt);
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_CMDQ_CTXT_SET,
+ cmdq_ctxt, in_size,
+ &cmdq_ctxt_out, &out_size, 0);
+ if (err || !out_size || cmdq_ctxt_out.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to set cmdq ctxt, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, cmdq_ctxt_out.status, out_size);
+ return -EFAULT;
+ }
+ }
+
+ cmdqs->status |= HIFC_CMDQ_ENABLE;
+ cmdqs->disable_flag = 0;
+
+ return 0;
+}
+
+void hifc_cmdq_flush_cmd(struct hifc_hwdev *hwdev,
+ struct hifc_cmdq *cmdq)
+{
+ struct hifc_cmdq_wqe *wqe;
+ struct hifc_cmdq_cmd_info *cmdq_info;
+ u16 ci, wqe_left, i;
+ u64 buf;
+
+ spin_lock_bh(&cmdq->cmdq_lock);
+ wqe_left = cmdq->wq->q_depth - (u16)atomic_read(&cmdq->wq->delta);
+ ci = MASKED_WQE_IDX(cmdq->wq, cmdq->wq->cons_idx);
+ for (i = 0; i < wqe_left; i++, ci++) {
+ ci = MASKED_WQE_IDX(cmdq->wq, ci);
+ cmdq_info = &cmdq->cmd_infos[ci];
+
+ if (cmdq_info->cmd_type == HIFC_CMD_TYPE_SET_ARM)
+ continue;
+
+ if (cmdq->cmdq_type == HIFC_CMDQ_ASYNC) {
+ wqe = hifc_get_wqebb_addr(cmdq->wq, ci);
+ buf = wqe->wqe_lcmd.buf_desc.saved_async_buf;
+ wqe->wqe_lcmd.buf_desc.saved_async_buf = 0;
+
+ hifc_be32_to_cpu((void *)&buf, sizeof(u64));
+ if (buf)
+ hifc_free_cmd_buf(hwdev,
+ (struct hifc_cmd_buf *)buf);
+ } else {
+ if (cmdq_info->done) {
+ complete(cmdq_info->done);
+ cmdq_info->done = NULL;
+ cmdq_info->cmpt_code = NULL;
+ cmdq_info->direct_resp = NULL;
+ cmdq_info->errcode = NULL;
+ }
+ }
+ }
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+}
+
+int hifc_reinit_cmdq_ctxts(struct hifc_hwdev *hwdev)
+{
+ struct hifc_cmdqs *cmdqs = hwdev->cmdqs;
+ enum hifc_cmdq_type cmdq_type;
+
+ cmdq_type = HIFC_CMDQ_SYNC;
+ for (; cmdq_type < HIFC_MAX_CMDQ_TYPES; cmdq_type++) {
+ hifc_cmdq_flush_cmd(hwdev, &cmdqs->cmdq[cmdq_type]);
+ cmdqs->cmdq[cmdq_type].wrapped = 1;
+ hifc_wq_wqe_pg_clear(cmdqs->cmdq[cmdq_type].wq);
+ }
+
+ return hifc_set_cmdq_ctxts(hwdev);
+}
+
+int hifc_cmdqs_init(struct hifc_hwdev *hwdev)
+{
+ struct hifc_cmdqs *cmdqs;
+ struct hifc_cmdq_ctxt *cmdq_ctxt;
+ enum hifc_cmdq_type type, cmdq_type;
+ size_t saved_wqs_size;
+ u32 max_wqe_size;
+ int err;
+
+ cmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL);
+ if (!cmdqs)
+ return -ENOMEM;
+
+ hwdev->cmdqs = cmdqs;
+ cmdqs->hwdev = hwdev;
+
+ saved_wqs_size = HIFC_MAX_CMDQ_TYPES * sizeof(struct hifc_wq);
+ cmdqs->saved_wqs = kzalloc(saved_wqs_size, GFP_KERNEL);
+ if (!cmdqs->saved_wqs) {
+ sdk_err(hwdev->dev_hdl, "Failed to allocate saved wqs\n");
+ err = -ENOMEM;
+ goto alloc_wqs_err;
+ }
+
+ cmdqs->cmd_buf_pool = dma_pool_create("hifc_cmdq", hwdev->dev_hdl,
+ HIFC_CMDQ_BUF_SIZE,
+ HIFC_CMDQ_BUF_SIZE, 0ULL);
+ if (!cmdqs->cmd_buf_pool) {
+ sdk_err(hwdev->dev_hdl, "Failed to create cmdq buffer pool\n");
+ err = -ENOMEM;
+ goto pool_create_err;
+ }
+
+ max_wqe_size = (u32)cmdq_wqe_size(WQE_LCMD_TYPE);
+ err = hifc_cmdq_alloc(&cmdqs->cmdq_pages, cmdqs->saved_wqs,
+ hwdev->dev_hdl, HIFC_MAX_CMDQ_TYPES,
+ hwdev->wq_page_size, CMDQ_WQEBB_SIZE,
+ HIFC_CMDQ_DEPTH, max_wqe_size);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to allocate cmdq\n");
+ goto cmdq_alloc_err;
+ }
+
+ cmdq_type = HIFC_CMDQ_SYNC;
+ for (; cmdq_type < HIFC_MAX_CMDQ_TYPES; cmdq_type++) {
+ err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,
+ &cmdqs->saved_wqs[cmdq_type], cmdq_type);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to initialize cmdq type :%d\n",
+ cmdq_type);
+ goto init_cmdq_err;
+ }
+
+ cmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;
+ cmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type],
+ &cmdqs->cmdq_pages, cmdq_ctxt);
+ }
+
+ err = hifc_set_cmdq_ctxts(hwdev);
+ if (err)
+ goto init_cmdq_err;
+
+ return 0;
+
+init_cmdq_err:
+ type = HIFC_CMDQ_SYNC;
+ for (; type < cmdq_type; type++)
+ free_cmdq(hwdev, &cmdqs->cmdq[type]);
+
+ hifc_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs,
+ HIFC_MAX_CMDQ_TYPES);
+
+cmdq_alloc_err:
+ dma_pool_destroy(cmdqs->cmd_buf_pool);
+
+pool_create_err:
+ kfree(cmdqs->saved_wqs);
+
+alloc_wqs_err:
+ kfree(cmdqs);
+
+ return err;
+}
+
+void hifc_cmdqs_free(struct hifc_hwdev *hwdev)
+{
+ struct hifc_cmdqs *cmdqs = hwdev->cmdqs;
+ enum hifc_cmdq_type cmdq_type = HIFC_CMDQ_SYNC;
+
+ cmdqs->status &= ~HIFC_CMDQ_ENABLE;
+
+ for (; cmdq_type < HIFC_MAX_CMDQ_TYPES; cmdq_type++) {
+ hifc_cmdq_flush_cmd(hwdev, &cmdqs->cmdq[cmdq_type]);
+ free_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]);
+ }
+
+ hifc_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs,
+ HIFC_MAX_CMDQ_TYPES);
+
+ dma_pool_destroy(cmdqs->cmd_buf_pool);
+
+ kfree(cmdqs->saved_wqs);
+
+ kfree(cmdqs);
+}
diff --git a/drivers/scsi/huawei/hifc/hifc_cmdq.h b/drivers/scsi/huawei/hifc/hifc_cmdq.h
new file mode 100644
index 000000000000..cb2ac81c5edc
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cmdq.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_CMDQ_H_
+#define HIFC_CMDQ_H_
+
+#define HIFC_DB_OFF 0x00000800
+
+#define HIFC_SCMD_DATA_LEN 16
+
+#define HIFC_CMDQ_DEPTH 4096
+
+#define HIFC_CMDQ_BUF_SIZE 2048U
+#define HIFC_CMDQ_BUF_HW_RSVD 8
+#define HIFC_CMDQ_MAX_DATA_SIZE \
+ (HIFC_CMDQ_BUF_SIZE - HIFC_CMDQ_BUF_HW_RSVD)
+#define WQ_PAGE_PFN_SHIFT 12
+#define WQ_BLOCK_PFN_SHIFT 9
+
+#define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT)
+#define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT)
+
+enum hifc_cmdq_type {
+ HIFC_CMDQ_SYNC,
+ HIFC_CMDQ_ASYNC,
+ HIFC_MAX_CMDQ_TYPES,
+};
+
+enum hifc_db_src_type {
+ HIFC_DB_SRC_CMDQ_TYPE,
+ HIFC_DB_SRC_L2NIC_SQ_TYPE,
+};
+
+enum hifc_cmdq_db_type {
+ HIFC_DB_SQ_RQ_TYPE,
+ HIFC_DB_CMDQ_TYPE,
+};
+
+/* CMDQ WQE CTRLS */
+struct hifc_cmdq_header {
+ u32 header_info;
+ u32 saved_data;
+};
+
+struct hifc_scmd_bufdesc {
+ u32 buf_len;
+ u32 rsvd;
+ u8 data[HIFC_SCMD_DATA_LEN];
+};
+
+struct hifc_lcmd_bufdesc {
+ struct hifc_sge sge;
+ u32 rsvd1;
+ u64 saved_async_buf;
+ u64 rsvd3;
+};
+
+struct hifc_cmdq_db {
+ u32 db_info;
+ u32 rsvd;
+};
+
+struct hifc_status {
+ u32 status_info;
+};
+
+struct hifc_ctrl {
+ u32 ctrl_info;
+};
+
+struct hifc_sge_resp {
+ struct hifc_sge sge;
+ u32 rsvd;
+};
+
+struct hifc_cmdq_completion {
+ /* HW Format */
+ union {
+ struct hifc_sge_resp sge_resp;
+ u64 direct_resp;
+ };
+};
+
+struct hifc_cmdq_wqe_scmd {
+ struct hifc_cmdq_header header;
+ struct hifc_cmdq_db db;
+ struct hifc_status status;
+ struct hifc_ctrl ctrl;
+ struct hifc_cmdq_completion completion;
+ struct hifc_scmd_bufdesc buf_desc;
+};
+
+struct hifc_cmdq_wqe_lcmd {
+ struct hifc_cmdq_header header;
+ struct hifc_status status;
+ struct hifc_ctrl ctrl;
+ struct hifc_cmdq_completion completion;
+ struct hifc_lcmd_bufdesc buf_desc;
+};
+
+struct hifc_cmdq_inline_wqe {
+ struct hifc_cmdq_wqe_scmd wqe_scmd;
+};
+
+struct hifc_cmdq_wqe {
+ /* HW Format */
+ union {
+ struct hifc_cmdq_inline_wqe inline_wqe;
+ struct hifc_cmdq_wqe_lcmd wqe_lcmd;
+ };
+};
+
+struct hifc_cmdq_arm_bit {
+ u32 q_type;
+ u32 q_id;
+};
+
+struct hifc_cmdq_ctxt_info {
+ u64 curr_wqe_page_pfn;
+ u64 wq_block_pfn;
+};
+
+struct hifc_cmdq_ctxt {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 cmdq_id;
+ u8 ppf_idx;
+
+ u8 rsvd1[4];
+
+ struct hifc_cmdq_ctxt_info ctxt_info;
+};
+
+enum hifc_cmdq_status {
+ HIFC_CMDQ_ENABLE = BIT(0),
+};
+
+enum hifc_cmdq_cmd_type {
+ HIFC_CMD_TYPE_NONE,
+ HIFC_CMD_TYPE_SET_ARM,
+ HIFC_CMD_TYPE_DIRECT_RESP,
+ HIFC_CMD_TYPE_SGE_RESP,
+ HIFC_CMD_TYPE_ASYNC,
+ HIFC_CMD_TYPE_TIMEOUT,
+ HIFC_CMD_TYPE_FAKE_TIMEOUT,
+};
+
+struct hifc_cmdq_cmd_info {
+ enum hifc_cmdq_cmd_type cmd_type;
+
+ struct completion *done;
+ int *errcode;
+ int *cmpt_code;
+ u64 *direct_resp;
+ u64 cmdq_msg_id;
+};
+
+struct hifc_cmdq {
+ struct hifc_wq *wq;
+
+ enum hifc_cmdq_type cmdq_type;
+ int wrapped;
+
+ /* spinlock for send cmdq commands */
+ spinlock_t cmdq_lock;
+
+ /* doorbell area */
+ u8 __iomem *db_base;
+
+ struct hifc_cmdq_ctxt cmdq_ctxt;
+
+ struct hifc_cmdq_cmd_info *cmd_infos;
+
+ struct hifc_hwdev *hwdev;
+};
+
+struct hifc_cmdqs {
+ struct hifc_hwdev *hwdev;
+
+ struct pci_pool *cmd_buf_pool;
+
+ struct hifc_wq *saved_wqs;
+
+ struct hifc_cmdq_pages cmdq_pages;
+ struct hifc_cmdq cmdq[HIFC_MAX_CMDQ_TYPES];
+
+ u32 status;
+ u32 disable_flag;
+};
+
+void hifc_cmdq_ceq_handler(void *hwdev, u32 ceqe_data);
+
+int hifc_reinit_cmdq_ctxts(struct hifc_hwdev *hwdev);
+
+bool hifc_cmdq_idle(struct hifc_cmdq *cmdq);
+
+int hifc_cmdqs_init(struct hifc_hwdev *hwdev);
+
+void hifc_cmdqs_free(struct hifc_hwdev *hwdev);
+
+void hifc_cmdq_flush_cmd(struct hifc_hwdev *hwdev,
+ struct hifc_cmdq *cmdq);
+
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_cqm_main.c b/drivers/scsi/huawei/hifc/hifc_cqm_main.c
new file mode 100644
index 000000000000..4cd048f1e662
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cqm_main.c
@@ -0,0 +1,694 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_cfg.h"
+#include "hifc_cqm_object.h"
+#include "hifc_cqm_main.h"
+
+#define GET_MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define GET_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+static void cqm_capability_init_check_ppf(void *ex_handle,
+ u32 *total_function_num)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct service_cap *service_capability = &handle->cfg_mgmt->svc_cap;
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ (handle->cqm_hdl);
+
+ if (cqm_handle->func_attribute.func_type == CQM_PPF) {
+ *total_function_num = service_capability->host_total_function;
+ cqm_handle->func_capability.timer_enable =
+ service_capability->timer_en;
+
+ cqm_info(handle->dev_hdl, "Cap init: total function num 0x%x\n",
+ *total_function_num);
+ cqm_info(handle->dev_hdl, "Cap init: timer_enable %d (1: enable; 0: disable)\n",
+ cqm_handle->func_capability.timer_enable);
+ }
+}
+
+void cqm_test_mode_init(struct cqm_handle_s *cqm_handle,
+ struct service_cap *service_capability)
+{
+ cqm_handle->func_capability.xid_alloc_mode =
+ service_capability->test_xid_alloc_mode;
+ cqm_handle->func_capability.gpa_check_enable =
+ service_capability->test_gpa_check_enable;
+}
+
+static s32 cqm_service_capability_init_for_each(
+ struct cqm_handle_s *cqm_handle,
+ struct service_cap *service_capability)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)cqm_handle->ex_handle;
+
+ cqm_info(handle->dev_hdl, "Cap init: fc is valid\n");
+ cqm_handle->func_capability.hash_number +=
+ service_capability->fc_cap.dev_fc_cap.max_parent_qpc_num;
+ cqm_handle->func_capability.hash_basic_size = CQM_HASH_BUCKET_SIZE_64;
+ cqm_handle->func_capability.qpc_number +=
+ service_capability->fc_cap.dev_fc_cap.max_parent_qpc_num;
+ cqm_handle->func_capability.qpc_basic_size =
+ GET_MAX(service_capability->fc_cap.parent_qpc_size,
+ cqm_handle->func_capability.qpc_basic_size);
+ cqm_handle->func_capability.qpc_alloc_static = true;
+ cqm_handle->func_capability.scqc_number +=
+ service_capability->fc_cap.dev_fc_cap.scq_num;
+ cqm_handle->func_capability.scqc_basic_size =
+ GET_MAX(service_capability->fc_cap.scqc_size,
+ cqm_handle->func_capability.scqc_basic_size);
+ cqm_handle->func_capability.srqc_number +=
+ service_capability->fc_cap.dev_fc_cap.srq_num;
+ cqm_handle->func_capability.srqc_basic_size =
+ GET_MAX(service_capability->fc_cap.srqc_size,
+ cqm_handle->func_capability.srqc_basic_size);
+ cqm_handle->func_capability.lun_number = CQM_LUN_FC_NUM;
+ cqm_handle->func_capability.lun_basic_size = CQM_LUN_SIZE_8;
+ cqm_handle->func_capability.taskmap_number = CQM_TASKMAP_FC_NUM;
+ cqm_handle->func_capability.taskmap_basic_size = PAGE_SIZE;
+ cqm_handle->func_capability.childc_number +=
+ service_capability->fc_cap.dev_fc_cap.max_child_qpc_num;
+ cqm_handle->func_capability.childc_basic_size =
+ GET_MAX(service_capability->fc_cap.child_qpc_size,
+ cqm_handle->func_capability.childc_basic_size);
+ cqm_handle->func_capability.pagesize_reorder = CQM_FC_PAGESIZE_ORDER;
+
+ return CQM_SUCCESS;
+}
+
+s32 cqm_service_capability_init(struct cqm_handle_s *cqm_handle,
+ struct service_cap *service_capability)
+{
+ cqm_handle->service.has_register = false;
+ cqm_handle->service.buf_order = 0;
+
+ if (cqm_service_capability_init_for_each(
+ cqm_handle,
+ service_capability) == CQM_FAIL)
+ return CQM_FAIL;
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_capability_init - Initialize capability of cqm function and service,
+ * need to read information from the configuration management module
+ * @ex_handle: handle of hwdev
+ */
+s32 cqm_capability_init(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct service_cap *service_capability = &handle->cfg_mgmt->svc_cap;
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ (handle->cqm_hdl);
+ u32 total_function_num = 0;
+ int err = 0;
+
+ cqm_capability_init_check_ppf(ex_handle, &total_function_num);
+
+ cqm_handle->func_capability.flow_table_based_conn_number =
+ service_capability->max_connect_num;
+ cqm_handle->func_capability.flow_table_based_conn_cache_number =
+ service_capability->max_stick2cache_num;
+ cqm_info(handle->dev_hdl, "Cap init: cfg max_conn_num 0x%x, max_cache_conn_num 0x%x\n",
+ cqm_handle->func_capability.flow_table_based_conn_number,
+ cqm_handle->func_capability.flow_table_based_conn_cache_number);
+
+ cqm_handle->func_capability.qpc_reserved = 0;
+ cqm_handle->func_capability.mpt_reserved = 0;
+ cqm_handle->func_capability.qpc_alloc_static = false;
+ cqm_handle->func_capability.scqc_alloc_static = false;
+
+ cqm_handle->func_capability.l3i_number = CQM_L3I_COMM_NUM;
+ cqm_handle->func_capability.l3i_basic_size = CQM_L3I_SIZE_8;
+
+ cqm_handle->func_capability.timer_number = CQM_TIMER_ALIGN_SCALE_NUM *
+ total_function_num;
+ cqm_handle->func_capability.timer_basic_size = CQM_TIMER_SIZE_32;
+
+ if (cqm_service_capability_init(cqm_handle, service_capability) ==
+ CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_service_capability_init));
+ err = CQM_FAIL;
+ goto out;
+ }
+
+ cqm_test_mode_init(cqm_handle, service_capability);
+
+ cqm_info(handle->dev_hdl, "Cap init: pagesize_reorder %d\n",
+ cqm_handle->func_capability.pagesize_reorder);
+ cqm_info(handle->dev_hdl, "Cap init: xid_alloc_mode %d, gpa_check_enable %d\n",
+ cqm_handle->func_capability.xid_alloc_mode,
+ cqm_handle->func_capability.gpa_check_enable);
+ cqm_info(handle->dev_hdl, "Cap init: qpc_alloc_mode %d, scqc_alloc_mode %d\n",
+ cqm_handle->func_capability.qpc_alloc_static,
+ cqm_handle->func_capability.scqc_alloc_static);
+ cqm_info(handle->dev_hdl, "Cap init: hash_number 0x%x\n",
+ cqm_handle->func_capability.hash_number);
+ cqm_info(handle->dev_hdl, "Cap init: qpc_number 0x%x, qpc_reserved 0x%x\n",
+ cqm_handle->func_capability.qpc_number,
+ cqm_handle->func_capability.qpc_reserved);
+ cqm_info(handle->dev_hdl, "Cap init: scqc_number 0x%x scqc_reserved 0x%x\n",
+ cqm_handle->func_capability.scqc_number,
+ cqm_handle->func_capability.scq_reserved);
+ cqm_info(handle->dev_hdl, "Cap init: srqc_number 0x%x\n",
+ cqm_handle->func_capability.srqc_number);
+ cqm_info(handle->dev_hdl, "Cap init: mpt_number 0x%x, mpt_reserved 0x%x\n",
+ cqm_handle->func_capability.mpt_number,
+ cqm_handle->func_capability.mpt_reserved);
+ cqm_info(handle->dev_hdl, "Cap init: gid_number 0x%x, lun_number 0x%x\n",
+ cqm_handle->func_capability.gid_number,
+ cqm_handle->func_capability.lun_number);
+ cqm_info(handle->dev_hdl, "Cap init: taskmap_number 0x%x, l3i_number 0x%x\n",
+ cqm_handle->func_capability.taskmap_number,
+ cqm_handle->func_capability.l3i_number);
+ cqm_info(handle->dev_hdl, "Cap init: timer_number 0x%x\n",
+ cqm_handle->func_capability.timer_number);
+ cqm_info(handle->dev_hdl, "Cap init: xid2cid_number 0x%x, reorder_number 0x%x\n",
+ cqm_handle->func_capability.xid2cid_number,
+ cqm_handle->func_capability.reorder_number);
+
+ return CQM_SUCCESS;
+
+out:
+ if (cqm_handle->func_attribute.func_type == CQM_PPF)
+ cqm_handle->func_capability.timer_enable = 0;
+
+ return err;
+}
+
+/**
+ * cqm_init - Initialize cqm
+ * @ex_handle: handle of hwdev
+ */
+s32 cqm_init(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ s32 ret = CQM_FAIL;
+
+ CQM_PTR_CHECK_RET(ex_handle, return CQM_FAIL, CQM_PTR_NULL(ex_handle));
+
+ cqm_handle = (struct cqm_handle_s *)kmalloc(sizeof(struct cqm_handle_s),
+ GFP_KERNEL | __GFP_ZERO);
+ CQM_PTR_CHECK_RET(cqm_handle, return CQM_FAIL,
+ CQM_ALLOC_FAIL(cqm_handle));
+ /* Clear memory to prevent other systems' memory from being cleared */
+ memset(cqm_handle, 0, sizeof(struct cqm_handle_s));
+
+ cqm_handle->ex_handle = handle;
+ cqm_handle->dev = (struct pci_dev *)(handle->pcidev_hdl);
+
+ handle->cqm_hdl = (void *)cqm_handle;
+
+ /* Clear statistics */
+ memset(&handle->hw_stats.cqm_stats, 0, sizeof(struct hifc_cqm_stats));
+
+ /* Read information of vf or pf */
+ cqm_handle->func_attribute = handle->hwif->attr;
+ cqm_info(handle->dev_hdl, "Func init: function type %d\n",
+ cqm_handle->func_attribute.func_type);
+
+ /* Read ability from configuration management module */
+ ret = cqm_capability_init(ex_handle);
+ if (ret == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_capability_init));
+ goto err1;
+ }
+
+ /* Initialize entries of memory table such as BAT/CLA/bitmap */
+ if (cqm_mem_init(ex_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_mem_init));
+ goto err1;
+ }
+
+ /* Initialize event callback */
+ if (cqm_event_init(ex_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_event_init));
+ goto err2;
+ }
+
+ /* Initialize doorbell */
+ if (cqm_db_init(ex_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_db_init));
+ goto err3;
+ }
+
+ /* The timer bitmap is set directly from the beginning through CQM,
+ * no longer set/clear the bitmap through ifconfig up/down
+ */
+ if (hifc_func_tmr_bitmap_set(ex_handle, 1) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, "Timer start: enable timer bitmap failed\n");
+ goto err5;
+ }
+
+ return CQM_SUCCESS;
+
+err5:
+ cqm_db_uninit(ex_handle);
+err3:
+ cqm_event_uninit(ex_handle);
+err2:
+ cqm_mem_uninit(ex_handle);
+err1:
+ handle->cqm_hdl = NULL;
+ kfree(cqm_handle);
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_uninit - Deinitialize the cqm, and is called once removing a function
+ * @ex_handle: handle of hwdev
+ */
+void cqm_uninit(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ s32 ret = CQM_FAIL;
+
+ CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle), return);
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_NO_RET(cqm_handle, CQM_PTR_NULL(cqm_handle), return);
+
+ /* The timer bitmap is set directly from the beginning through CQM,
+ * no longer set/clear the bitmap through ifconfig up/down
+ */
+ cqm_info(handle->dev_hdl, "Timer stop: disable timer\n");
+ if (hifc_func_tmr_bitmap_set(ex_handle, 0) != CQM_SUCCESS)
+ cqm_err(handle->dev_hdl, "Timer stop: disable timer bitmap failed\n");
+
+ /* Stopping timer, release the resource
+ * after a delay of one or two milliseconds
+ */
+ if ((cqm_handle->func_attribute.func_type == CQM_PPF) &&
+ (cqm_handle->func_capability.timer_enable == CQM_TIMER_ENABLE)) {
+ cqm_info(handle->dev_hdl, "Timer stop: hifc ppf timer stop\n");
+ ret = hifc_ppf_tmr_stop(handle);
+
+ if (ret != CQM_SUCCESS) {
+ cqm_info(handle->dev_hdl, "Timer stop: hifc ppf timer stop, ret=%d\n",
+ ret);
+ /* The timer fails to stop
+ * and does not affect resource release
+ */
+ }
+ usleep_range(900, 1000);
+ }
+
+ /* Release hardware doorbell */
+ cqm_db_uninit(ex_handle);
+
+ /* Cancel the callback of chipif */
+ cqm_event_uninit(ex_handle);
+
+ /* Release all table items
+ * and require the service to release all objects
+ */
+ cqm_mem_uninit(ex_handle);
+
+ /* Release cqm_handle */
+ handle->cqm_hdl = NULL;
+ kfree(cqm_handle);
+}
+
+/**
+ * cqm_mem_init - Initialize related memory of cqm,
+ * including all levels of entries
+ * @ex_handle: handle of hwdev
+ */
+s32 cqm_mem_init(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+
+ if (cqm_bat_init(cqm_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_init));
+ return CQM_FAIL;
+ }
+
+ if (cqm_cla_init(cqm_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_init));
+ goto err1;
+ }
+
+ if (cqm_bitmap_init(cqm_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bitmap_init));
+ goto err2;
+ }
+
+ if (cqm_object_table_init(cqm_handle) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_object_table_init));
+ goto err3;
+ }
+
+ return CQM_SUCCESS;
+
+err3:
+ cqm_bitmap_uninit(cqm_handle);
+err2:
+ cqm_cla_uninit(cqm_handle);
+err1:
+ cqm_bat_uninit(cqm_handle);
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_mem_uninit - Deinitialize related memory of cqm,
+ * including all levels of entries
+ * @ex_handle: handle of hwdev
+ */
+void cqm_mem_uninit(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+
+ cqm_object_table_uninit(cqm_handle);
+ cqm_bitmap_uninit(cqm_handle);
+ cqm_cla_uninit(cqm_handle);
+ cqm_bat_uninit(cqm_handle);
+}
+
+/**
+ * cqm_event_init - Initialize the event callback of cqm
+ * @ex_handle: handle of hwdev
+ */
+s32 cqm_event_init(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+
+ /* Register ceq and aeq callbacks with chipif */
+ if (hifc_aeq_register_swe_cb(ex_handle,
+ HIFC_STATEFULL_EVENT,
+ cqm_aeq_callback) != CHIPIF_SUCCESS) {
+ cqm_err(handle->dev_hdl, "Event: fail to register aeq callback\n");
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_event_uninit - Deinitialize the event callback of cqm
+ * @ex_handle: handle of hwdev
+ */
+void cqm_event_uninit(void *ex_handle)
+{
+ (void)hifc_aeq_unregister_swe_cb(ex_handle, HIFC_STATEFULL_EVENT);
+}
+
+/**
+ * cqm_db_addr_alloc - Apply for a page of hardware doorbell and dwqe,
+ * with the same index, all obtained are physical addresses
+ * each function has up to 1K
+ * @ex_handle: handle of hwdev
+ * @db_addr: the address of doorbell
+ * @dwqe_addr: the address of dwqe
+ */
+s32 cqm_db_addr_alloc(void *ex_handle, void __iomem **db_addr,
+ void __iomem **dwqe_addr)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+
+ CQM_PTR_CHECK_RET(ex_handle, return CQM_FAIL, CQM_PTR_NULL(ex_handle));
+ CQM_PTR_CHECK_RET(db_addr, return CQM_FAIL, CQM_PTR_NULL(db_addr));
+ CQM_PTR_CHECK_RET(dwqe_addr, return CQM_FAIL, CQM_PTR_NULL(dwqe_addr));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_db_addr_alloc_cnt);
+
+ return hifc_alloc_db_addr(ex_handle, db_addr, dwqe_addr);
+}
+
+/**
+ * cqm_db_init - Initialize doorbell of cqm
+ * @ex_handle: handle of hwdev
+ */
+s32 cqm_db_init(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_service_s *service = NULL;
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+
+ /* Assign hardware doorbell for service */
+ service = &cqm_handle->service;
+
+ if (cqm_db_addr_alloc(ex_handle,
+ &service->hardware_db_vaddr,
+ &service->dwqe_vaddr) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_db_addr_alloc));
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_db_addr_free - Release a page of hardware doorbell and dwqe
+ * @ex_handle: handle of hwdev
+ * @db_addr: the address of doorbell
+ * @dwqe_addr: the address of dwqe
+ */
+void cqm_db_addr_free(void *ex_handle, void __iomem *db_addr,
+ void __iomem *dwqe_addr)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+
+ CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle), return);
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_db_addr_free_cnt);
+
+ hifc_free_db_addr(ex_handle, db_addr, dwqe_addr);
+}
+
+/**
+ * cqm_db_uninit - Deinitialize doorbell of cqm
+ * @ex_handle: handle of hwdev
+ */
+void cqm_db_uninit(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_service_s *service = NULL;
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+
+ /* Release hardware doorbell */
+ service = &cqm_handle->service;
+
+ cqm_db_addr_free(ex_handle, service->hardware_db_vaddr,
+ service->dwqe_vaddr);
+}
+
+/**
+ * cqm_aeq_callback - cqm module callback processing of aeq
+ * @ex_handle: handle of hwdev
+ * @event: the input type of event
+ * @data: the input data
+ */
+u8 cqm_aeq_callback(void *ex_handle, u8 event, u64 data)
+{
+#define CQM_AEQ_BASE_T_FC 48
+#define CQM_AEQ_BASE_T_FCOE 56
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_service_s *service = NULL;
+ struct service_register_template_s *service_template = NULL;
+ u8 event_level = FAULT_LEVEL_MAX;
+
+ CQM_PTR_CHECK_RET(ex_handle, return event_level,
+ CQM_PTR_NULL(ex_handle));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_aeq_callback_cnt[event]);
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_RET(cqm_handle, return event_level,
+ CQM_PTR_NULL(cqm_handle));
+
+ if (event >= (u8)CQM_AEQ_BASE_T_FC &&
+ (event < (u8)CQM_AEQ_BASE_T_FCOE)) {
+ service = &cqm_handle->service;
+ service_template = &service->service_template;
+
+ if (!service_template->aeq_callback) {
+ cqm_err(handle->dev_hdl, "Event: service aeq_callback unregistered\n");
+ } else {
+ service_template->aeq_callback(
+ service_template->service_handle, event, data);
+ }
+
+ return event_level;
+ }
+
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(event));
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_service_register - Service driver registers callback template with cqm
+ * @ex_handle: handle of hwdev
+ * @service_template: the template of service registration
+ */
+s32 cqm_service_register(void *ex_handle,
+ struct service_register_template_s *service_template)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_service_s *service = NULL;
+
+ CQM_PTR_CHECK_RET(ex_handle, return CQM_FAIL, CQM_PTR_NULL(ex_handle));
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_RET(cqm_handle, return CQM_FAIL,
+ CQM_PTR_NULL(cqm_handle));
+ CQM_PTR_CHECK_RET(service_template, return CQM_FAIL,
+ CQM_PTR_NULL(service_template));
+
+ service = &cqm_handle->service;
+
+ if (service->has_register == true) {
+ cqm_err(handle->dev_hdl, "Service register: service has registered\n");
+ return CQM_FAIL;
+ }
+
+ service->has_register = true;
+ (void)memcpy((void *)(&service->service_template),
+ (void *)service_template,
+ sizeof(struct service_register_template_s));
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_service_unregister - Service-driven cancellation to CQM
+ * @ex_handle: handle of hwdev
+ * @service_type: the type of service module
+ */
+void cqm_service_unregister(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_service_s *service = NULL;
+
+ CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle), return);
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_NO_RET(cqm_handle, CQM_PTR_NULL(cqm_handle), return);
+
+ service = &cqm_handle->service;
+
+ service->has_register = false;
+ memset(&service->service_template, 0,
+ sizeof(struct service_register_template_s));
+}
+
+/**
+ * cqm_cmd_alloc - Apply for a cmd buffer, the buffer size is fixed at 2K,
+ * the buffer content is not cleared, but the service needs to be cleared
+ * @ex_handle: handle of hwdev
+ */
+struct cqm_cmd_buf_s *cqm_cmd_alloc(void *ex_handle)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+
+ CQM_PTR_CHECK_RET(ex_handle, return NULL, CQM_PTR_NULL(ex_handle));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_cmd_alloc_cnt);
+
+ return (struct cqm_cmd_buf_s *)hifc_alloc_cmd_buf(ex_handle);
+}
+
+/**
+ * cqm_cmd_free - Free a cmd buffer
+ * @ex_handle: handle of hwdev
+ * @cmd_buf: the cmd buffer which needs freeing memory for
+ */
+void cqm_cmd_free(void *ex_handle, struct cqm_cmd_buf_s *cmd_buf)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+
+ CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle), return);
+ CQM_PTR_CHECK_NO_RET(cmd_buf, CQM_PTR_NULL(cmd_buf), return);
+ CQM_PTR_CHECK_NO_RET(cmd_buf->buf, CQM_PTR_NULL(buf), return);
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_cmd_free_cnt);
+
+ hifc_free_cmd_buf(ex_handle, (struct hifc_cmd_buf *)cmd_buf);
+}
+
+/**
+ * cqm_send_cmd_box - Send a cmd in box mode,
+ * the interface will hang the completed amount, causing sleep
+ * @ex_handle: handle of hwdev
+ * @ack_type: the type of ack
+ * @mod: the mode of cqm send
+ * @cmd: the input cmd
+ * @buf_in: the input buffer of cqm_cmd
+ * @buf_out: the output buffer of cqm_cmd
+ * @timeout: exceeding the time limit will cause sleep
+ */
+s32 cqm_send_cmd_box(void *ex_handle, u8 ack_type, u8 mod, u8 cmd,
+ struct cqm_cmd_buf_s *buf_in,
+ struct cqm_cmd_buf_s *buf_out, u32 timeout)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+
+ CQM_PTR_CHECK_RET(ex_handle, return CQM_FAIL, CQM_PTR_NULL(ex_handle));
+ CQM_PTR_CHECK_RET(buf_in, return CQM_FAIL, CQM_PTR_NULL(buf_in));
+ CQM_PTR_CHECK_RET(buf_in->buf, return CQM_FAIL, CQM_PTR_NULL(buf));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_send_cmd_box_cnt);
+
+ return hifc_cmdq_detail_resp(ex_handle, ack_type, mod, cmd,
+ (struct hifc_cmd_buf *)buf_in,
+ (struct hifc_cmd_buf *)buf_out, timeout);
+}
+
+/**
+ * cqm_ring_hardware_db - Knock hardware doorbell
+ * @ex_handle: handle of hwdev
+ * @service_type: each kernel mode will be allocated a page of hardware doorbell
+ * @db_count: PI exceeding 64b in doorbell[7:0]
+ * @db: doorbell content, organized by the business,
+ * if there is a small-end conversion, the business needs to be completed
+ */
+s32 cqm_ring_hardware_db(void *ex_handle, u32 service_type, u8 db_count, u64 db)
+{
+ struct hifc_hwdev *handle;
+ struct cqm_handle_s *cqm_handle;
+ struct cqm_service_s *service;
+
+ handle = (struct hifc_hwdev *)ex_handle;
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ service = &cqm_handle->service;
+
+ /* Write all before the doorbell */
+ wmb();
+ *((u64 *)service->hardware_db_vaddr + db_count) = db;
+
+ return CQM_SUCCESS;
+}
diff --git a/drivers/scsi/huawei/hifc/hifc_cqm_main.h b/drivers/scsi/huawei/hifc/hifc_cqm_main.h
new file mode 100644
index 000000000000..70b0c9ae0609
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cqm_main.h
@@ -0,0 +1,366 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+#ifndef __CQM_MAIN_H__
+#define __CQM_MAIN_H__
+
+#define CHIPIF_SUCCESS 0
+#define CQM_TIMER_ENABLE 1
+
+enum cqm_object_type_e {
+ CQM_OBJECT_ROOT_CTX = 0,
+ CQM_OBJECT_SERVICE_CTX,
+ CQM_OBJECT_NONRDMA_EMBEDDED_RQ = 10,
+ CQM_OBJECT_NONRDMA_EMBEDDED_SQ,
+ CQM_OBJECT_NONRDMA_SRQ,
+ CQM_OBJECT_NONRDMA_EMBEDDED_CQ,
+ CQM_OBJECT_NONRDMA_SCQ,
+};
+
+struct service_register_template_s {
+ u32 service_type;
+ u32 srq_ctx_size; /* srq,scq context_size config */
+ u32 scq_ctx_size;
+ void *service_handle; /* ceq/aeq callback fun */
+
+ void (*aeq_callback)(void *service_handle, u8 event_type, u64 val);
+};
+
+struct cqm_service_s {
+ bool has_register;
+ void __iomem *hardware_db_vaddr;
+ void __iomem *dwqe_vaddr;
+ u32 buf_order; /* size of per buf 2^buf_order page */
+ struct service_register_template_s service_template;
+};
+
+struct cqm_func_capability_s {
+ bool qpc_alloc_static; /* Allocate qpc memory dynamicly/statically */
+ bool scqc_alloc_static;
+ u8 timer_enable; /* whether timer enable */
+
+ u32 flow_table_based_conn_number;
+ u32 flow_table_based_conn_cache_number; /* Maximum number in cache */
+ u32 bloomfilter_length; /* Bloomfilter table size, aligned by 64B */
+ /* The starting position of the bloomfilter table in the cache */
+ u32 bloomfilter_addr;
+ u32 qpc_reserved; /* Reserved bits in bitmap */
+ u32 mpt_reserved; /* There are also reserved bits in ROCE/IWARP mpt */
+ /* All basic_size must be 2^n aligned */
+ u32 hash_number;
+ /* Number of hash buckets, BAT table fill size is
+ * aligned with 64 buckets, at least 64
+ */
+ u32 hash_basic_size;
+ /* Hash bucket size is 64B, including 5 valid
+ * entries and 1 nxt_entry
+ */
+ u32 qpc_number;
+ u32 qpc_basic_size;
+
+ /* Note: for cqm specail test */
+ u32 pagesize_reorder;
+ bool xid_alloc_mode;
+ bool gpa_check_enable;
+ u32 scq_reserved;
+
+ u32 mpt_number;
+ u32 mpt_basic_size;
+ u32 scqc_number;
+ u32 scqc_basic_size;
+ u32 srqc_number;
+ u32 srqc_basic_size;
+
+ u32 gid_number;
+ u32 gid_basic_size;
+ u32 lun_number;
+ u32 lun_basic_size;
+ u32 taskmap_number;
+ u32 taskmap_basic_size;
+ u32 l3i_number;
+ u32 l3i_basic_size;
+ u32 childc_number;
+ u32 childc_basic_size;
+ u32 child_qpc_id_start; /* Child ctx of FC is global addressing */
+ /* The maximum number of child ctx in
+ * chip is 8096
+ */
+ u32 childc_number_all_function;
+
+ u32 timer_number;
+ u32 timer_basic_size;
+ u32 xid2cid_number;
+ u32 xid2cid_basic_size;
+ u32 reorder_number;
+ u32 reorder_basic_size;
+};
+
+#define CQM_PF TYPE_PF
+#define CQM_PPF TYPE_PPF
+#define CQM_BAT_ENTRY_MAX (16)
+#define CQM_BAT_ENTRY_SIZE (16)
+
+struct cqm_buf_list_s {
+ void *va;
+ dma_addr_t pa;
+ u32 refcount;
+};
+
+struct cqm_buf_s {
+ struct cqm_buf_list_s *buf_list;
+ struct cqm_buf_list_s direct;
+ u32 page_number; /* page_number=2^n buf_number */
+ u32 buf_number; /* buf_list node count */
+ u32 buf_size; /* buf_size=2^n PAGE_SIZE */
+};
+
+struct cqm_bitmap_s {
+ ulong *table;
+ u32 max_num;
+ u32 last;
+ /* The index that cannot be allocated is reserved in the front */
+ u32 reserved_top;
+ /* Lock for bitmap allocation */
+ spinlock_t lock;
+};
+
+struct completion;
+struct cqm_object_s {
+ u32 service_type;
+ u32 object_type; /* context,queue,mpt,mtt etc */
+ u32 object_size;
+ /* for queue, ctx, MPT Byte */
+ atomic_t refcount;
+ struct completion free;
+ void *cqm_handle;
+};
+
+struct cqm_object_table_s {
+ struct cqm_object_s **table;
+ u32 max_num;
+ rwlock_t lock;
+};
+
+struct cqm_cla_table_s {
+ u32 type;
+ u32 max_buffer_size;
+ u32 obj_num;
+ bool alloc_static; /* Whether the buffer is statically allocated */
+ u32 cla_lvl;
+ /* The value of x calculated by the cacheline, used for chip */
+ u32 cacheline_x;
+ /* The value of y calculated by the cacheline, used for chip */
+ u32 cacheline_y;
+ /* The value of z calculated by the cacheline, used for chip */
+ u32 cacheline_z;
+ /* The value of x calculated by the obj_size, used for software */
+ u32 x;
+ /* The value of y calculated by the obj_size, used for software */
+ u32 y;
+ /* The value of z calculated by the obj_size, used for software */
+ u32 z;
+ struct cqm_buf_s cla_x_buf;
+ struct cqm_buf_s cla_y_buf;
+ struct cqm_buf_s cla_z_buf;
+ u32 trunk_order;/* A continuous physical page contains 2^order pages */
+ u32 obj_size;
+ /* Lock for cla buffer allocation and free */
+ struct mutex lock;
+ struct cqm_bitmap_s bitmap;
+ /* The association mapping table of index and object */
+ struct cqm_object_table_s obj_table;
+};
+
+typedef void (*init_handler)(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap);
+
+struct cqm_cla_entry_init_s {
+ u32 type;
+ init_handler cqm_cla_init_handler;
+};
+
+struct cqm_bat_table_s {
+ u32 bat_entry_type[CQM_BAT_ENTRY_MAX];
+ u8 bat[CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE];
+ struct cqm_cla_table_s entry[CQM_BAT_ENTRY_MAX];
+ u32 bat_size;
+};
+
+struct cqm_handle_s {
+ struct hifc_hwdev *ex_handle;
+ struct pci_dev *dev;
+ struct hifc_func_attr func_attribute; /* vf or pf */
+ struct cqm_func_capability_s func_capability;
+ struct cqm_service_s service;
+ struct cqm_bat_table_s bat_table;
+
+ struct list_head node;
+};
+
+struct cqm_cmd_buf_s {
+ void *buf;
+ dma_addr_t dma;
+ u16 size;
+};
+
+struct cqm_queue_header_s {
+ u64 doorbell_record;
+ u64 ci_record;
+ u64 rsv1; /* the share area bettween driver and ucode */
+ u64 rsv2; /* the share area bettween driver and ucode*/
+};
+
+struct cqm_queue_s {
+ struct cqm_object_s object;
+ u32 index; /* embedded queue QP has not index, SRQ and SCQ have */
+ void *priv; /* service driver private info */
+ u32 current_q_doorbell;
+ u32 current_q_room;
+ /* nonrdma: only select q_room_buf_1 for q_room_buf */
+ struct cqm_buf_s q_room_buf_1;
+ struct cqm_buf_s q_room_buf_2;
+ struct cqm_queue_header_s *q_header_vaddr;
+ dma_addr_t q_header_paddr;
+ u8 *q_ctx_vaddr; /* SRQ and SCQ ctx space */
+ dma_addr_t q_ctx_paddr;
+ u32 valid_wqe_num;
+ /*add for srq*/
+ u8 *tail_container;
+ u8 *head_container;
+ u8 queue_link_mode; /*link,ring */
+};
+
+struct cqm_nonrdma_qinfo_s {
+ struct cqm_queue_s common;
+ u32 wqe_size;
+ /* The number of wqe contained in each buf (excluding link wqe),
+ * For srq, it is the number of wqe contained in 1 container
+ */
+ u32 wqe_per_buf;
+ u32 q_ctx_size;
+ /* When different services use different sizes of ctx, a large ctx will
+ * occupy multiple consecutive indexes of the bitmap
+ */
+ u32 index_count;
+ u32 container_size;
+};
+
+/* service context, QPC, mpt */
+struct cqm_qpc_mpt_s {
+ struct cqm_object_s object;
+ u32 xid;
+ dma_addr_t paddr;
+ void *priv; /* service driver private info */
+ u8 *vaddr;
+};
+
+struct cqm_qpc_mpt_info_s {
+ struct cqm_qpc_mpt_s common;
+ /* When different services use different sizes of QPC, large QPC/mpt
+ * will occupy multiple consecutive indexes of the bitmap
+ */
+ u32 index_count;
+};
+
+#define CQM_ADDR_COMBINE(high_addr, low_addr) \
+ ((((dma_addr_t)(high_addr)) << 32) + ((dma_addr_t)(low_addr)))
+#define CQM_ADDR_HI(addr) ((u32)((u64)(addr) >> 32))
+#define CQM_ADDR_LW(addr) ((u32)((u64)(addr) & 0xffffffff))
+#define CQM_HASH_BUCKET_SIZE_64 (64)
+#define CQM_LUN_SIZE_8 (8)
+#define CQM_L3I_SIZE_8 (8)
+#define CQM_TIMER_SIZE_32 (32)
+#define CQM_LUN_FC_NUM (64)
+#define CQM_TASKMAP_FC_NUM (4)
+#define CQM_L3I_COMM_NUM (64)
+#define CQM_TIMER_SCALE_NUM (2*1024)
+#define CQM_TIMER_ALIGN_WHEEL_NUM (8)
+#define CQM_TIMER_ALIGN_SCALE_NUM \
+ (CQM_TIMER_SCALE_NUM*CQM_TIMER_ALIGN_WHEEL_NUM)
+#define CQM_FC_PAGESIZE_ORDER (0)
+#define CQM_QHEAD_ALIGN_ORDER (6)
+
+s32 cqm_mem_init(void *ex_handle);
+void cqm_mem_uninit(void *ex_handle);
+s32 cqm_event_init(void *ex_handle);
+void cqm_event_uninit(void *ex_handle);
+s32 cqm_db_init(void *ex_handle);
+void cqm_db_uninit(void *ex_handle);
+s32 cqm_init(void *ex_handle);
+void cqm_uninit(void *ex_handle);
+s32 cqm_service_register(void *ex_handle,
+ struct service_register_template_s *service_template);
+void cqm_service_unregister(void *ex_handle);
+s32 cqm_ring_hardware_db(void *ex_handle,
+ u32 service_type,
+ u8 db_count, u64 db);
+s32 cqm_send_cmd_box(void *ex_handle, u8 ack_type, u8 mod, u8 cmd,
+ struct cqm_cmd_buf_s *buf_in,
+ struct cqm_cmd_buf_s *buf_out,
+ u32 timeout);
+u8 cqm_aeq_callback(void *ex_handle, u8 event, u64 data);
+void cqm_object_delete(struct cqm_object_s *object);
+struct cqm_cmd_buf_s *cqm_cmd_alloc(void *ex_handle);
+void cqm_cmd_free(void *ex_handle, struct cqm_cmd_buf_s *cmd_buf);
+struct cqm_queue_s *cqm_object_fc_srq_create(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 wqe_number,
+ u32 wqe_size,
+ void *object_priv);
+struct cqm_qpc_mpt_s *cqm_object_qpc_mpt_create(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 object_size,
+ void *object_priv,
+ u32 index);
+struct cqm_queue_s *cqm_object_nonrdma_queue_create(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 wqe_number,
+ u32 wqe_size,
+ void *object_priv);
+
+#define CQM_PTR_NULL(x) "%s: "#x" is null\n", __func__
+#define CQM_ALLOC_FAIL(x) "%s: "#x" alloc fail\n", __func__
+#define CQM_MAP_FAIL(x) "%s: "#x" map fail\n", __func__
+#define CQM_FUNCTION_FAIL(x) "%s: "#x" return failure\n", __func__
+#define CQM_WRONG_VALUE(x) "%s: "#x" %u is wrong\n", __func__, (u32)x
+
+#define cqm_err(dev, format, ...) \
+ dev_err(dev, "[CQM]"format, ##__VA_ARGS__)
+#define cqm_warn(dev, format, ...) \
+ dev_warn(dev, "[CQM]"format, ##__VA_ARGS__)
+#define cqm_notice(dev, format, ...) \
+ dev_notice(dev, "[CQM]"format, ##__VA_ARGS__)
+#define cqm_info(dev, format, ...) \
+ dev_info(dev, "[CQM]"format, ##__VA_ARGS__)
+#define cqm_dbg(format, ...)
+
+#define CQM_PTR_CHECK_RET(ptr, ret, desc) \
+ do {\
+ if (unlikely(NULL == (ptr))) {\
+ pr_err("[CQM]"desc);\
+ ret; \
+ } \
+ } while (0)
+
+#define CQM_PTR_CHECK_NO_RET(ptr, desc, ret) \
+ do {\
+ if (unlikely((ptr) == NULL)) {\
+ pr_err("[CQM]"desc);\
+ ret; \
+ } \
+ } while (0)
+#define CQM_CHECK_EQUAL_RET(dev_hdl, actual, expect, ret, desc) \
+ do {\
+ if (unlikely((expect) != (actual))) {\
+ cqm_err(dev_hdl, desc);\
+ ret; \
+ } \
+ } while (0)
+
+#endif /* __CQM_MAIN_H__ */
diff --git a/drivers/scsi/huawei/hifc/hifc_cqm_object.c b/drivers/scsi/huawei/hifc/hifc_cqm_object.c
new file mode 100644
index 000000000000..406b13f92e64
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cqm_object.c
@@ -0,0 +1,3599 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_cfg.h"
+#include "hifc_cqm_object.h"
+#include "hifc_cqm_main.h"
+#define common_section
+
+#define CQM_MOD_CQM 8
+#define CQM_HARDWARE_DOORBELL 1
+/**
+ * cqm_swab64 - Convert a memory block to another endian by 8 byte basis
+ * @addr: start address of the memory block
+ * @cnt: the number of 8 byte basis in the memory block
+ */
+void cqm_swab64(u8 *addr, u32 cnt)
+{
+ u32 i = 0;
+ u64 *temp = (u64 *)addr;
+ u64 value = 0;
+
+ for (i = 0; i < cnt; i++) {
+ value = __swab64(*temp);
+ *temp = value;
+ temp++;
+ }
+}
+
+/**
+ * cqm_swab32 - Convert a memory block to another endian by 4 byte basis
+ * @addr: start address of the memory block
+ * @cnt: the number of 4 byte basis in the memory block
+ */
+void cqm_swab32(u8 *addr, u32 cnt)
+{
+ u32 i = 0;
+ u32 *temp = (u32 *)addr;
+ u32 value = 0;
+
+ for (i = 0; i < cnt; i++) {
+ value = __swab32(*temp);
+ *temp = value;
+ temp++;
+ }
+}
+
+/**
+ * cqm_shift - Find the base logarithm of two
+ * @data: the input data
+ */
+s32 cqm_shift(u32 data)
+{
+ s32 shift = -1;
+
+ do {
+ data >>= 1;
+ shift++;
+ } while (data);
+
+ return shift;
+}
+
+/**
+ * cqm_check_align - Check whether the data is aligned as the base of 2^n
+ * @data: the input data
+ */
+bool cqm_check_align(u32 data)
+{
+ if (data == 0)
+ return false;
+
+ do {
+ /* If data can be divided exactly by 2,
+ * it right shifts one bit
+ */
+ if ((data & 0x1) == 0) {
+ data >>= 1;
+ } else {
+ /* If data can not be divided exactly by 2
+ * it is not the base of 2^n,return false
+ */
+ return false;
+ }
+ } while (data != 1);
+
+ return true;
+}
+
+/**
+ * cqm_kmalloc_align - Alloc memory whose start address is aligned as the basis
+ * of 2^n
+ * @size: the size of memory allocated
+ * @flags: the type of memory allocated
+ * @align_order: the basis for aligning
+ */
+static void *cqm_kmalloc_align(size_t size, gfp_t flags, u16 align_order)
+{
+ void *orig_addr = NULL;
+ void *align_addr = NULL;
+ void *index_addr = NULL;
+
+ orig_addr = kmalloc(size + ((u64)1 << align_order) + sizeof(void *),
+ flags);
+ if (!orig_addr)
+ return NULL;
+
+ index_addr = (void *)((char *)orig_addr + sizeof(void *));
+ align_addr = (void *)((((u64)index_addr +
+ ((u64)1 << align_order) - 1) >> align_order) << align_order);
+
+ /* Record the original memory address for memory release. */
+ index_addr = (void *)((char *)align_addr - sizeof(void *));
+ *(void **)index_addr = orig_addr;
+
+ cqm_dbg("allocate %lu bytes aligned address: %p, original address: %p\n",
+ size, align_addr, orig_addr);
+
+ return align_addr;
+}
+
+/**
+ * cqm_kfree_align - Free memory whose start address is aligned as the basis of
+ * 2^n
+ * @addr: aligned address which would be free
+ */
+static void cqm_kfree_align(void *addr)
+{
+ void *index_addr = NULL;
+
+ /* Release original memory address */
+ index_addr = (void *)((char *)addr - sizeof(void *));
+
+ cqm_dbg("free aligned address: %p, original address: %p\n",
+ addr, *(void **)index_addr);
+
+ kfree(*(void **)index_addr);
+}
+
+/**
+ * cqm_buf_alloc_page - Alloc total pages memory for buffers
+ * @cqm_handle: handle of cqm
+ * @buf: the buffer which needs allocating memory for
+ */
+s32 cqm_buf_alloc_page(struct cqm_handle_s *cqm_handle, struct cqm_buf_s *buf)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ u32 order = 0;
+ void *va = NULL;
+ s32 i = 0;
+
+ order = get_order(buf->buf_size);
+
+ /*Here to allocate for every buffer's page for non-ovs*/
+ for (i = 0; i < (s32)buf->buf_number; i++) {
+ va = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+ if (!va) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
+ break;
+ }
+ /* Pages should be initialized to 0 after applied
+ * especially related to the hash table
+ */
+ memset(va, 0, buf->buf_size);
+ buf->buf_list[i].va = va;
+ }
+
+ if (i != buf->buf_number) {
+ i--;
+ for (; i >= 0; i--) {
+ free_pages((ulong)(buf->buf_list[i].va), order);
+ buf->buf_list[i].va = NULL;
+ }
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_buf_alloc_map - Buffer pci mapping
+ * @cqm_handle: handle of cqm
+ * @buf: the buffer which needs map
+ */
+s32 cqm_buf_alloc_map(struct cqm_handle_s *cqm_handle, struct cqm_buf_s *buf)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct pci_dev *dev = cqm_handle->dev;
+ s32 i = 0;
+ void *va = NULL;
+
+ for (i = 0; i < (s32)buf->buf_number; i++) {
+ va = buf->buf_list[i].va;
+ buf->buf_list[i].pa =
+ pci_map_single(dev, va, buf->buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(dev, buf->buf_list[i].pa)) {
+ cqm_err(handle->dev_hdl, CQM_MAP_FAIL(buf_list));
+ break;
+ }
+ }
+
+ if (i != buf->buf_number) {
+ i--;
+ for (; i >= 0; i--) {
+ pci_unmap_single(dev, buf->buf_list[i].pa,
+ buf->buf_size, PCI_DMA_BIDIRECTIONAL);
+ }
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_buf_alloc_direct - Buffer pci direct remapping
+ * @cqm_handle: handle of cqm
+ * @buf: the buffer which needs remap
+ */
+s32 cqm_buf_alloc_direct(struct cqm_handle_s *cqm_handle,
+ struct cqm_buf_s *buf, bool direct)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct page **pages = NULL;
+ u32 order = 0;
+ u32 i = 0;
+ u32 j = 0;
+
+ order = get_order(buf->buf_size);
+
+ if (direct == true) {
+ pages = (struct page **)
+ vmalloc(sizeof(struct page *) * buf->page_number);
+ if (!pages) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(pages));
+ return CQM_FAIL;
+ }
+
+ for (i = 0; i < buf->buf_number; i++) {
+ for (j = 0; j < ((u32)1 << order); j++) {
+ pages[(i << order) + j] = (struct page *)
+ (void *)virt_to_page(
+ (u8 *)(buf->buf_list[i].va) +
+ (PAGE_SIZE * j));
+ }
+ }
+
+ /*lint -save -e648
+ *Shield alarm for kernel functions' vmapping
+ */
+ buf->direct.va = vmap(pages, buf->page_number,
+ VM_MAP, PAGE_KERNEL);
+ /*lint -restore*/
+ vfree(pages);
+ if (!buf->direct.va) {
+ cqm_err(handle->dev_hdl, CQM_MAP_FAIL(buf->direct.va));
+ return CQM_FAIL;
+ }
+ } else {
+ buf->direct.va = NULL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_buf_alloc - Allocate for buffer and dma for the struct cqm_buf_s
+ * @cqm_handle: handle of cqm
+ * @buf: the buffer which needs allocating memory for and dma
+ */
+s32 cqm_buf_alloc(struct cqm_handle_s *cqm_handle,
+ struct cqm_buf_s *buf, bool direct)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct pci_dev *dev = cqm_handle->dev;
+ u32 order = 0;
+ s32 i = 0;
+
+ order = get_order(buf->buf_size);
+
+ /* Allocate for the descriptor space of buffer lists */
+ buf->buf_list = (struct cqm_buf_list_s *)
+ vmalloc(buf->buf_number *
+ sizeof(struct cqm_buf_list_s));
+
+ CQM_PTR_CHECK_RET(buf->buf_list, return CQM_FAIL,
+ CQM_ALLOC_FAIL(buf_list));
+ memset(buf->buf_list, 0,
+ buf->buf_number * sizeof(struct cqm_buf_list_s));
+
+ /* Allocate for every buffer's page */
+ if (cqm_buf_alloc_page(cqm_handle, buf) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_buf_alloc_page));
+ goto err1;
+ }
+
+ /* Buffer pci remapping */
+ if (cqm_buf_alloc_map(cqm_handle, buf) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_buf_alloc_map));
+ goto err2;
+ }
+
+ /* Buffer pci mapping */
+ if (cqm_buf_alloc_direct(cqm_handle, buf, direct) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_buf_alloc_direct));
+ goto err3;
+ }
+
+ return CQM_SUCCESS;
+
+err3:
+ for (i = 0; i < (s32)buf->buf_number; i++) {
+ pci_unmap_single(dev, buf->buf_list[i].pa, buf->buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+ }
+err2:
+ for (i = 0; i < (s32)buf->buf_number; i++) {
+ free_pages((ulong)(buf->buf_list[i].va), order);
+ buf->buf_list[i].va = NULL;
+ }
+err1:
+ vfree(buf->buf_list);
+ buf->buf_list = NULL;
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_cla_cache_invalid - Set the chip logical address cache invalid
+ * @cqm_handle: handle of cqm
+ * @gpa: global physical address
+ * @cache_size: chip cache size
+ */
+s32 cqm_cla_cache_invalid(struct cqm_handle_s *cqm_handle, dma_addr_t gpa,
+ u32 cache_size)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_cmd_buf_s *buf_in = NULL;
+ struct cqm_cla_cache_invalid_cmd_s *cmd = NULL;
+ s32 ret = CQM_FAIL;
+
+ buf_in = cqm_cmd_alloc((void *)(cqm_handle->ex_handle));
+ CQM_PTR_CHECK_RET(buf_in, return CQM_FAIL,
+ CQM_ALLOC_FAIL(buf_in));
+ buf_in->size = sizeof(struct cqm_cla_cache_invalid_cmd_s);
+
+ /* Fill command format, and turn into big endian */
+ cmd = (struct cqm_cla_cache_invalid_cmd_s *)(buf_in->buf);
+ cmd->cache_size = cache_size;
+ cmd->gpa_h = CQM_ADDR_HI(gpa);
+ cmd->gpa_l = CQM_ADDR_LW(gpa);
+
+ cqm_swab32((u8 *)cmd,
+ (sizeof(struct cqm_cla_cache_invalid_cmd_s) >> 2));
+
+ /* cmdq send a cmd */
+ ret = cqm_send_cmd_box((void *)(cqm_handle->ex_handle),
+ CQM_CMD_ACK_TYPE_CMDQ,
+ CQM_MOD_CQM, CQM_CMD_T_CLA_CACHE_INVALID,
+ buf_in, NULL, CQM_CMD_TIMEOUT);
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_send_cmd_box));
+ cqm_err(handle->dev_hdl, "Cla cache invalid: cqm_send_cmd_box_ret=%d\n",
+ ret);
+ cqm_err(handle->dev_hdl, "Cla cache invalid: cla_cache_invalid_cmd: 0x%x 0x%x 0x%x\n",
+ cmd->gpa_h, cmd->gpa_l, cmd->cache_size);
+ }
+
+ cqm_cmd_free((void *)(cqm_handle->ex_handle), buf_in);
+ return ret;
+}
+
+/**
+ * cqm_buf_free - Free buffer space and dma for the struct cqm_buf_s
+ * @buf: the buffer which needs freeing memory for
+ * @dev: specific pci device
+ */
+void cqm_buf_free(struct cqm_buf_s *buf, struct pci_dev *dev)
+{
+ u32 order = 0;
+ s32 i = 0;
+
+ order = get_order(buf->buf_size);
+
+ if (buf->direct.va) {
+ vunmap(buf->direct.va);
+ buf->direct.va = NULL;
+ }
+
+ if (buf->buf_list) {
+ for (i = 0; i < (s32)(buf->buf_number); i++) {
+ if (buf->buf_list[i].va) {
+ pci_unmap_single(dev, buf->buf_list[i].pa,
+ buf->buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+ free_pages((ulong)(buf->buf_list[i].va), order);
+ buf->buf_list[i].va = NULL;
+ }
+ }
+
+ vfree(buf->buf_list);
+ buf->buf_list = NULL;
+ }
+}
+
+/**
+ * __free_cache_inv - Free cache and make buffer list invalid
+ * @cqm_handle: handle of cqm
+ * @buf: the buffer which needs freeing memory for
+ * @inv_flag: invalid or not
+ * @order:the basis for aligning
+ * @buf_idx:buffer index
+ */
+static void __free_cache_inv(struct cqm_handle_s *cqm_handle,
+ struct cqm_buf_s *buf, s32 *inv_flag,
+ u32 order, s32 buf_idx)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ if (handle->chip_present_flag) {
+ *inv_flag = cqm_cla_cache_invalid(cqm_handle,
+ buf->buf_list[buf_idx].pa,
+ PAGE_SIZE << order);
+ if (*inv_flag != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, "Buffer free: fail to invalid buf_list pa cache, inv_flag=%d\n",
+ *inv_flag);
+ }
+ }
+
+ pci_unmap_single(cqm_handle->dev, buf->buf_list[buf_idx].pa,
+ buf->buf_size, PCI_DMA_BIDIRECTIONAL);
+
+ free_pages((unsigned long)(buf->buf_list[buf_idx].va), order);
+
+ buf->buf_list[buf_idx].va = NULL;
+}
+
+/**
+ * cqm_buf_free_cache_inv - Free cache and make buffer list invalid
+ * @cqm_handle: handle of cqm
+ * @buf: the buffer which needs freeing memory for
+ * @inv_flag: invalid or not
+ */
+void cqm_buf_free_cache_inv(struct cqm_handle_s *cqm_handle,
+ struct cqm_buf_s *buf, s32 *inv_flag)
+{
+ u32 order = 0;
+ s32 i = 0;
+
+ order = get_order(buf->buf_size);
+
+ if (buf->direct.va) {
+ vunmap(buf->direct.va);
+ buf->direct.va = NULL;
+ }
+
+ if (buf->buf_list) {
+ for (i = 0; i < (s32)(buf->buf_number); i++) {
+ if (buf->buf_list[i].va) {
+ __free_cache_inv(cqm_handle, buf,
+ inv_flag, order, i);
+ }
+ }
+
+ vfree(buf->buf_list);
+ buf->buf_list = NULL;
+ }
+}
+
+#define bat_cla_section
+
+/**
+ * cqm_bat_update - Send cmds to the tile to update the BAT table through cmdq
+ * @cqm_handle: cqm handle
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_bat_update(struct cqm_handle_s *cqm_handle)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_cmd_buf_s *buf_in = NULL;
+ s32 ret = CQM_FAIL;
+ struct cqm_bat_update_cmd_s *bat_update_cmd = NULL;
+
+ /* Allocate a cmd and fill */
+ buf_in = cqm_cmd_alloc((void *)(cqm_handle->ex_handle));
+ CQM_PTR_CHECK_RET(buf_in, return CQM_FAIL, CQM_ALLOC_FAIL(buf_in));
+ buf_in->size = sizeof(struct cqm_bat_update_cmd_s);
+
+ bat_update_cmd = (struct cqm_bat_update_cmd_s *)(buf_in->buf);
+ bat_update_cmd->byte_len = cqm_handle->bat_table.bat_size;
+ bat_update_cmd->offset = 0;
+ memcpy(bat_update_cmd->data, cqm_handle->bat_table.bat,
+ bat_update_cmd->byte_len);
+
+ /*Big endian conversion*/
+ cqm_swab32((u8 *)bat_update_cmd,
+ sizeof(struct cqm_bat_update_cmd_s) >> 2);
+
+ /* send a cmd */
+ ret = cqm_send_cmd_box((void *)(cqm_handle->ex_handle),
+ CQM_CMD_ACK_TYPE_CMDQ, CQM_MOD_CQM,
+ CQM_CMD_T_BAT_UPDATE, buf_in,
+ NULL, CQM_CMD_TIMEOUT);
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_send_cmd_box));
+ cqm_err(handle->dev_hdl, "Bat update: send_cmd_box ret=%d\n",
+ ret);
+ cqm_cmd_free((void *)(cqm_handle->ex_handle), buf_in);
+ return CQM_FAIL;
+ }
+
+ /* Free a cmd */
+ cqm_cmd_free((void *)(cqm_handle->ex_handle), buf_in);
+
+ return CQM_SUCCESS;
+}
+
+s32 cqm_bat_init_ft(struct cqm_handle_s *cqm_handle,
+ struct cqm_bat_table_s *bat_table,
+ enum func_type function_type)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ if (function_type == CQM_PF || function_type == CQM_PPF) {
+ bat_table->bat_entry_type[0] = CQM_BAT_ENTRY_T_CFG;
+ bat_table->bat_entry_type[1] = CQM_BAT_ENTRY_T_HASH;
+ bat_table->bat_entry_type[2] = CQM_BAT_ENTRY_T_QPC;
+ bat_table->bat_entry_type[3] = CQM_BAT_ENTRY_T_SCQC;
+ bat_table->bat_entry_type[4] = CQM_BAT_ENTRY_T_LUN;
+ bat_table->bat_entry_type[5] = CQM_BAT_ENTRY_T_TASKMAP;
+ bat_table->bat_entry_type[6] = CQM_BAT_ENTRY_T_L3I;
+ bat_table->bat_entry_type[7] = CQM_BAT_ENTRY_T_CHILDC;
+ bat_table->bat_entry_type[8] = CQM_BAT_ENTRY_T_TIMER;
+ bat_table->bat_entry_type[9] = CQM_BAT_ENTRY_T_XID2CID;
+ bat_table->bat_entry_type[10] = CQM_BAT_ENTRY_T_REORDER;
+ bat_table->bat_size = CQM_BAT_SIZE_FT_PF;
+ } else {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(function_type));
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_bat_init - Initialize the BAT table, only select the items to be
+ * initialized and arrange the entry order, the content of the BAT table entry
+ * needs to be filled after the CLA allocation
+ * @cqm_handle: cqm handle
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_bat_init(struct cqm_handle_s *cqm_handle)
+{
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ u32 i = 0;
+
+ memset(bat_table, 0, sizeof(struct cqm_bat_table_s));
+
+ /* Initialize the type of each bat entry */
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++)
+ bat_table->bat_entry_type[i] = CQM_BAT_ENTRY_T_INVALID;
+
+ if (cqm_bat_init_ft(cqm_handle, bat_table,
+ cqm_handle->func_attribute.func_type) == CQM_FAIL) {
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_bat_uninit - Deinitialize BAT table
+ * @cqm_handle: cqm handle
+ */
+void cqm_bat_uninit(struct cqm_handle_s *cqm_handle)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ u32 i = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++)
+ bat_table->bat_entry_type[i] = CQM_BAT_ENTRY_T_INVALID;
+
+ memset(bat_table->bat, 0, CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE);
+
+ /* Notify the chip to refresh the BAT table */
+ if (cqm_bat_update(cqm_handle) != CQM_SUCCESS)
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_update));
+}
+
+static void cqm_bat_config_entry_size(
+ struct cqm_cla_table_s *cla_table,
+ struct cqm_bat_entry_standerd_s *bat_entry_standerd)
+{
+ /* Except for QPC of 256/512/1024, the others are all cacheline 256B,
+ * and the conversion will be done inside the chip
+ */
+ if (cla_table->obj_size > CQM_CHIP_CACHELINE) {
+ if (cla_table->obj_size == 512) {
+ bat_entry_standerd->entry_size = CQM_BAT_ENTRY_SIZE_512;
+ } else {
+ bat_entry_standerd->entry_size =
+ CQM_BAT_ENTRY_SIZE_1024;
+ }
+ bat_entry_standerd->max_number =
+ cla_table->max_buffer_size / cla_table->obj_size;
+ } else {
+ bat_entry_standerd->entry_size = CQM_BAT_ENTRY_SIZE_256;
+ bat_entry_standerd->max_number =
+ cla_table->max_buffer_size / CQM_CHIP_CACHELINE;
+ }
+}
+
+void cqm_bat_fill_cla_std_entry(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u8 *entry_base_addr, u32 entry_type,
+ u8 gpa_check_enable)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_bat_entry_standerd_s *bat_entry_standerd = NULL;
+ dma_addr_t pa = 0;
+
+ if (cla_table->obj_num == 0) {
+ cqm_info(handle->dev_hdl, "Cla alloc: cla_type %u, obj_num=0, don't init bat entry\n",
+ cla_table->type);
+ return;
+ }
+
+ bat_entry_standerd = (struct cqm_bat_entry_standerd_s *)entry_base_addr;
+ cqm_bat_config_entry_size(cla_table, bat_entry_standerd);
+ bat_entry_standerd->max_number = bat_entry_standerd->max_number - 1;
+
+ bat_entry_standerd->bypass = CQM_BAT_NO_BYPASS_CACHE;
+ bat_entry_standerd->z = cla_table->cacheline_z;
+ bat_entry_standerd->y = cla_table->cacheline_y;
+ bat_entry_standerd->x = cla_table->cacheline_x;
+ bat_entry_standerd->cla_level = cla_table->cla_lvl;
+
+ if (cla_table->cla_lvl == CQM_CLA_LVL_0)
+ pa = cla_table->cla_z_buf.buf_list[0].pa;
+ else if (cla_table->cla_lvl == CQM_CLA_LVL_1)
+ pa = cla_table->cla_y_buf.buf_list[0].pa;
+ else
+ pa = cla_table->cla_x_buf.buf_list[0].pa;
+
+ bat_entry_standerd->cla_gpa_h = CQM_ADDR_HI(pa);
+ if (entry_type == CQM_BAT_ENTRY_T_REORDER) {
+ /* Reorder does not support GPA validity check */
+ bat_entry_standerd->cla_gpa_l = CQM_ADDR_LW(pa);
+ } else {
+ /* GPA is valid when gpa[0]=1 */
+ bat_entry_standerd->cla_gpa_l =
+ CQM_ADDR_LW(pa) | gpa_check_enable;
+ }
+}
+
+static void cqm_bat_fill_cla_cfg(struct cqm_handle_s *cqm_handle,
+ u8 *entry_base_addr)
+{
+ struct cqm_bat_entry_cfg_s *bat_entry_cfg =
+ (struct cqm_bat_entry_cfg_s *)entry_base_addr;
+
+ bat_entry_cfg->cur_conn_cache = 0;
+ bat_entry_cfg->max_conn_cache =
+ cqm_handle->func_capability.flow_table_based_conn_cache_number;
+ bat_entry_cfg->cur_conn_num_h_4 = 0;
+ bat_entry_cfg->cur_conn_num_l_16 = 0;
+ bat_entry_cfg->max_conn_num =
+ cqm_handle->func_capability.flow_table_based_conn_number;
+ /* Align by 64 buckets, shift right 6 bits */
+ if ((cqm_handle->func_capability.hash_number >> 6) != 0) {
+ /* After shift right 6 bits, the value should - 1 for the hash
+ * value
+ */
+ bat_entry_cfg->bucket_num =
+ ((cqm_handle->func_capability.hash_number >> 6) - 1);
+ }
+ if (cqm_handle->func_capability.bloomfilter_length != 0) {
+ bat_entry_cfg->bloom_filter_len =
+ cqm_handle->func_capability.bloomfilter_length - 1;
+ bat_entry_cfg->bloom_filter_addr =
+ cqm_handle->func_capability.bloomfilter_addr;
+ }
+}
+
+static void cqm_bat_fill_cla_taskmap(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u8 *entry_base_addr)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_bat_entry_taskmap_s *bat_entry_taskmap =
+ (struct cqm_bat_entry_taskmap_s *)entry_base_addr;
+ if (cqm_handle->func_capability.taskmap_number != 0) {
+ bat_entry_taskmap->gpa0_h =
+ (u32)(cla_table->cla_z_buf.buf_list[0].pa >> 32);
+ bat_entry_taskmap->gpa0_l =
+ (u32)(cla_table->cla_z_buf.buf_list[0].pa & 0xffffffff);
+
+ bat_entry_taskmap->gpa1_h =
+ (u32)(cla_table->cla_z_buf.buf_list[1].pa >> 32);
+ bat_entry_taskmap->gpa1_l =
+ (u32)(cla_table->cla_z_buf.buf_list[1].pa & 0xffffffff);
+
+ bat_entry_taskmap->gpa2_h =
+ (u32)(cla_table->cla_z_buf.buf_list[2].pa >> 32);
+ bat_entry_taskmap->gpa2_l =
+ (u32)(cla_table->cla_z_buf.buf_list[2].pa & 0xffffffff);
+
+ bat_entry_taskmap->gpa3_h =
+ (u32)(cla_table->cla_z_buf.buf_list[3].pa >> 32);
+ bat_entry_taskmap->gpa3_l =
+ (u32)(cla_table->cla_z_buf.buf_list[3].pa & 0xffffffff);
+
+ cqm_info(handle->dev_hdl, "Cla alloc: taskmap bat entry: 0x%x 0x%x, 0x%x 0x%x, 0x%x 0x%x, 0x%x 0x%x\n",
+ bat_entry_taskmap->gpa0_h, bat_entry_taskmap->gpa0_l,
+ bat_entry_taskmap->gpa1_h, bat_entry_taskmap->gpa1_l,
+ bat_entry_taskmap->gpa2_h, bat_entry_taskmap->gpa2_l,
+ bat_entry_taskmap->gpa3_h, bat_entry_taskmap->gpa3_l);
+ }
+}
+
+/**
+ * cqm_bat_fill_cla - Fill the base address of the cla table into the bat table
+ * @cqm_handle: cqm handle
+ */
+void cqm_bat_fill_cla(struct cqm_handle_s *cqm_handle)
+{
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ u32 entry_type = CQM_BAT_ENTRY_T_INVALID;
+ u8 *entry_base_addr = NULL;
+ u32 i = 0;
+ u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable;
+
+ /* Fill each item according to the arranged BAT table */
+ entry_base_addr = bat_table->bat;
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ entry_type = bat_table->bat_entry_type[i];
+ if (entry_type == CQM_BAT_ENTRY_T_CFG) {
+ cqm_bat_fill_cla_cfg(cqm_handle, entry_base_addr);
+ entry_base_addr += sizeof(struct cqm_bat_entry_cfg_s);
+ } else if (entry_type == CQM_BAT_ENTRY_T_TASKMAP) {
+ cqm_bat_fill_cla_taskmap(cqm_handle,
+ &bat_table->entry[i],
+ entry_base_addr);
+ entry_base_addr +=
+ sizeof(struct cqm_bat_entry_taskmap_s);
+ } else if ((entry_type == CQM_BAT_ENTRY_T_INVALID) ||
+ ((entry_type == CQM_BAT_ENTRY_T_TIMER) &&
+ (cqm_handle->func_attribute.func_type != CQM_PPF))) {
+ /* When entry_type is invalid, or the timer entry under
+ * PF does not need to apply for memory and bat filling
+ */
+ entry_base_addr += CQM_BAT_ENTRY_SIZE;
+ } else {
+ cla_table = &bat_table->entry[i];
+ cqm_bat_fill_cla_std_entry(cqm_handle, cla_table,
+ entry_base_addr, entry_type,
+ gpa_check_enable);
+ entry_base_addr +=
+ sizeof(struct cqm_bat_entry_standerd_s);
+ }
+ /* Checks if entry_base_addr is out of bounds */
+ if (entry_base_addr >=
+ (bat_table->bat + CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE))
+ break;
+ }
+}
+
+static void cqm_cla_xyz_cacheline_lvl1(struct cqm_cla_table_s *cla_table,
+ u32 trunk_size)
+{
+ s32 shift = 0;
+
+ if (cla_table->obj_size >= CQM_CHIP_CACHELINE) {
+ cla_table->cacheline_z = cla_table->z;
+ cla_table->cacheline_y = cla_table->y;
+ cla_table->cacheline_x = cla_table->x;
+ } else {
+ shift = cqm_shift(trunk_size / CQM_CHIP_CACHELINE);
+ cla_table->cacheline_z = shift ? (shift - 1) : (shift);
+ cla_table->cacheline_y = CQM_MAX_INDEX_BIT;
+ cla_table->cacheline_x = 0;
+ }
+}
+
+s32 cqm_cla_xyz_lvl1(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u32 trunk_size)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_y_buf = NULL;
+ struct cqm_buf_s *cla_z_buf = NULL;
+ dma_addr_t *base = NULL;
+ s32 shift = 0;
+ u32 i = 0;
+ s32 ret = CQM_FAIL;
+ u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable;
+
+ if (cla_table->type == CQM_BAT_ENTRY_T_REORDER)
+ gpa_check_enable = 0;
+
+ cla_table->cla_lvl = CQM_CLA_LVL_1;
+
+ shift = cqm_shift(trunk_size / cla_table->obj_size);
+ cla_table->z = shift ? (shift - 1) : (shift);
+ cla_table->y = CQM_MAX_INDEX_BIT;
+ cla_table->x = 0;
+ cqm_cla_xyz_cacheline_lvl1(cla_table, trunk_size);
+
+ /* Allocate y buf space */
+ cla_y_buf = &cla_table->cla_y_buf;
+ cla_y_buf->buf_size = trunk_size;
+ cla_y_buf->buf_number = 1;
+ cla_y_buf->page_number = cla_y_buf->buf_number <<
+ cla_table->trunk_order;
+ ret = cqm_buf_alloc(cqm_handle, cla_y_buf, false);
+
+ CQM_CHECK_EQUAL_RET(handle->dev_hdl, ret, CQM_SUCCESS, return CQM_FAIL,
+ CQM_ALLOC_FAIL(lvl_1_y_buf));
+
+ /* Allocate z buf space */
+ cla_z_buf = &cla_table->cla_z_buf;
+ cla_z_buf->buf_size = trunk_size;
+ cla_z_buf->buf_number = ALIGN(cla_table->max_buffer_size, trunk_size) /
+ trunk_size;
+ cla_z_buf->page_number = cla_z_buf->buf_number <<
+ cla_table->trunk_order;
+ /* Requires static allocation of all buffer space */
+ if (cla_table->alloc_static == true) {
+ if (cqm_buf_alloc(cqm_handle, cla_z_buf, false) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_1_z_buf));
+ cqm_buf_free(cla_y_buf, cqm_handle->dev);
+ return CQM_FAIL;
+ }
+
+ /* Fill gpa of z buf list into y buf */
+ base = (dma_addr_t *)(cla_y_buf->buf_list->va);
+ for (i = 0; i < cla_z_buf->buf_number; i++) {
+ /*gpa[0]=1 means this GPA is valid*/
+ *base = (cla_z_buf->buf_list[i].pa | gpa_check_enable);
+ base++;
+ }
+
+ /* big-endian conversion */
+ cqm_swab64((u8 *)(cla_y_buf->buf_list->va),
+ cla_z_buf->buf_number);
+ } else {
+ /* Only initialize and allocate buf list space, buffer spaces
+ * are dynamically allocated in service
+ */
+ cla_z_buf->buf_list = (struct cqm_buf_list_s *)
+ vmalloc(cla_z_buf->buf_number *
+ sizeof(struct cqm_buf_list_s));
+
+ if (!cla_z_buf->buf_list) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_1_z_buf));
+ cqm_buf_free(cla_y_buf, cqm_handle->dev);
+ return CQM_FAIL;
+ }
+ memset(cla_z_buf->buf_list, 0,
+ cla_z_buf->buf_number * sizeof(struct cqm_buf_list_s));
+ }
+
+ return CQM_SUCCESS;
+}
+
+static s32 cqm_cla_yz_lvl2_static(struct cqm_handle_s *cqm_handle,
+ struct cqm_buf_s *cla_y_buf,
+ struct cqm_buf_s *cla_z_buf,
+ u8 gpa_check_enable)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ dma_addr_t *base = NULL;
+ u32 i = 0;
+
+ if (cqm_buf_alloc(cqm_handle, cla_z_buf, false) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_2_z_buf));
+ return CQM_FAIL;
+ }
+
+ /* The virtual address of y buf is remapped for software access */
+ if (cqm_buf_alloc(cqm_handle, cla_y_buf, true) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_2_y_buf));
+ cqm_buf_free(cla_z_buf, cqm_handle->dev);
+ return CQM_FAIL;
+ }
+
+ /* Fill gpa of z buf list into y buf */
+ base = (dma_addr_t *)(cla_y_buf->direct.va);
+ for (i = 0; i < cla_z_buf->buf_number; i++) {
+ /*gpa[0]=1 means this GPA is valid*/
+ *base = (cla_z_buf->buf_list[i].pa | gpa_check_enable);
+ base++;
+ }
+
+ /* big-endian conversion */
+ cqm_swab64((u8 *)(cla_y_buf->direct.va), cla_z_buf->buf_number);
+
+ return CQM_SUCCESS;
+}
+
+static void cqm_cla_yz_lvl2_init_cacheline(struct cqm_cla_table_s *cla_table,
+ u32 trunk_size)
+{
+ s32 shift = 0;
+
+ if (cla_table->obj_size >= CQM_CHIP_CACHELINE) {
+ cla_table->cacheline_z = cla_table->z;
+ cla_table->cacheline_y = cla_table->y;
+ cla_table->cacheline_x = cla_table->x;
+ } else {
+ shift = cqm_shift(trunk_size / CQM_CHIP_CACHELINE);
+ cla_table->cacheline_z = shift ? (shift - 1) : (shift);
+ shift = cqm_shift(trunk_size / sizeof(dma_addr_t));
+ cla_table->cacheline_y = cla_table->cacheline_z + shift;
+ cla_table->cacheline_x = CQM_MAX_INDEX_BIT;
+ }
+}
+
+s32 cqm_cla_xyz_lvl2(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u32 trunk_size)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_x_buf = NULL;
+ struct cqm_buf_s *cla_y_buf = NULL;
+ struct cqm_buf_s *cla_z_buf = NULL;
+ dma_addr_t *base = NULL;
+ s32 shift = 0;
+ u32 i = 0;
+ s32 ret = CQM_FAIL;
+ u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable;
+
+ if (cla_table->type == CQM_BAT_ENTRY_T_REORDER)
+ gpa_check_enable = 0;
+
+ cla_table->cla_lvl = CQM_CLA_LVL_2;
+
+ shift = cqm_shift(trunk_size / cla_table->obj_size);
+ cla_table->z = shift ? (shift - 1) : (shift);
+ shift = cqm_shift(trunk_size / sizeof(dma_addr_t));
+ cla_table->y = cla_table->z + shift;
+ cla_table->x = CQM_MAX_INDEX_BIT;
+
+ cqm_cla_yz_lvl2_init_cacheline(cla_table, trunk_size);
+
+ /* Allocate x buf space */
+ cla_x_buf = &cla_table->cla_x_buf;
+ cla_x_buf->buf_size = trunk_size;
+ cla_x_buf->buf_number = 1;
+ cla_x_buf->page_number = cla_x_buf->buf_number <<
+ cla_table->trunk_order;
+
+ ret = cqm_buf_alloc(cqm_handle, cla_x_buf, false);
+ CQM_CHECK_EQUAL_RET(handle->dev_hdl, ret, CQM_SUCCESS, return CQM_FAIL,
+ CQM_ALLOC_FAIL(lvl_2_x_buf));
+
+ /* Allocate y buf and z buf space */
+ cla_z_buf = &cla_table->cla_z_buf;
+ cla_z_buf->buf_size = trunk_size;
+ cla_z_buf->buf_number = ALIGN(cla_table->max_buffer_size, trunk_size) /
+ trunk_size;
+ cla_z_buf->page_number = cla_z_buf->buf_number <<
+ cla_table->trunk_order;
+
+ cla_y_buf = &cla_table->cla_y_buf;
+ cla_y_buf->buf_size = trunk_size;
+ cla_y_buf->buf_number =
+ (ALIGN(cla_z_buf->buf_number * sizeof(dma_addr_t),
+ trunk_size)) / trunk_size;
+
+ cla_y_buf->page_number = cla_y_buf->buf_number <<
+ cla_table->trunk_order;
+
+ /* Requires static allocation of all buffer space */
+ if (cla_table->alloc_static == true) {
+ if (cqm_cla_yz_lvl2_static(cqm_handle,
+ cla_y_buf,
+ cla_z_buf,
+ gpa_check_enable) == CQM_FAIL) {
+ cqm_buf_free(cla_x_buf, cqm_handle->dev);
+ return CQM_FAIL;
+ }
+ /* Fill gpa of y buf list into x buf */
+ base = (dma_addr_t *)(cla_x_buf->buf_list->va);
+ for (i = 0; i < cla_y_buf->buf_number; i++) {
+ /* gpa[0]=1 means this GPA is valid */
+ *base = (cla_y_buf->buf_list[i].pa | gpa_check_enable);
+ base++;
+ }
+
+ /* big-endian conversion */
+ cqm_swab64((u8 *)(cla_x_buf->buf_list->va),
+ cla_y_buf->buf_number);
+ } else {
+ /* Only initialize and allocate buf list space, buffer spaces
+ * are allocated in service
+ */
+ cla_z_buf->buf_list = (struct cqm_buf_list_s *)
+ vmalloc(cla_z_buf->buf_number *
+ sizeof(struct cqm_buf_list_s));
+ if (!cla_z_buf->buf_list) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_2_z_buf));
+ cqm_buf_free(cla_x_buf, cqm_handle->dev);
+ return CQM_FAIL;
+ }
+ memset(cla_z_buf->buf_list, 0,
+ cla_z_buf->buf_number * sizeof(struct cqm_buf_list_s));
+
+ cla_y_buf->buf_list = (struct cqm_buf_list_s *)
+ vmalloc(cla_y_buf->buf_number *
+ sizeof(struct cqm_buf_list_s));
+
+ if (!cla_y_buf->buf_list) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_2_y_buf));
+ cqm_buf_free(cla_z_buf, cqm_handle->dev);
+ cqm_buf_free(cla_x_buf, cqm_handle->dev);
+ return CQM_FAIL;
+ }
+ memset(cla_y_buf->buf_list, 0,
+ cla_y_buf->buf_number * sizeof(struct cqm_buf_list_s));
+ }
+
+ return CQM_SUCCESS;
+}
+
+static s32 cqm_cla_xyz_check(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ if (cla_table->obj_num == 0) {
+ /* If the capability is set to 0, the CLA does not need to be
+ * initialized and exits directly
+ */
+ cqm_info(handle->dev_hdl, "Cla alloc: cla_type %u, obj_num=0, don't alloc buffer\n",
+ cla_table->type);
+ return CQM_SUCCESS;
+ }
+
+ /* Check whether obj_size is aligned with 2^n, and error is reported in
+ * case of 0 and 1
+ */
+ if (cqm_check_align(cla_table->obj_size) == false) {
+ cqm_err(handle->dev_hdl, "Cla alloc: cla_type %u, obj_size 0x%x is not align on 2^n\n",
+ cla_table->type, cla_table->obj_size);
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_cla_xyz - Calculate how many levels of cla tables and allocate space
+ * for each level of cla tables
+ * @cqm_handle: cqm handle
+ * @cla_table: cla table
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_cla_xyz(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_z_buf = NULL;
+ u32 trunk_size = 0;
+ s32 ret = CQM_FAIL;
+
+ if (cqm_cla_xyz_check(cqm_handle, cla_table) == CQM_FAIL)
+ return CQM_FAIL;
+
+ trunk_size = PAGE_SIZE << cla_table->trunk_order;
+
+ if (trunk_size < cla_table->obj_size) {
+ cqm_err(handle->dev_hdl, "Cla alloc: cla type %u, obj_size 0x%x is out of trunk size\n",
+ cla_table->type, cla_table->obj_size);
+ return CQM_FAIL;
+ }
+
+ /* Level 0 CLA: The buffer occupies little space, and can be assigned to
+ * cla_z_buf during initialization
+ */
+ if (cla_table->max_buffer_size <= trunk_size) {
+ cla_table->cla_lvl = CQM_CLA_LVL_0;
+
+ cla_table->z = CQM_MAX_INDEX_BIT;
+ cla_table->y = 0;
+ cla_table->x = 0;
+
+ cla_table->cacheline_z = cla_table->z;
+ cla_table->cacheline_y = cla_table->y;
+ cla_table->cacheline_x = cla_table->x;
+
+ /* Allocate z buf space */
+ cla_z_buf = &cla_table->cla_z_buf;
+ cla_z_buf->buf_size = trunk_size;
+ cla_z_buf->buf_number = 1;
+ cla_z_buf->page_number =
+ cla_z_buf->buf_number << cla_table->trunk_order;
+ ret = cqm_buf_alloc(cqm_handle, cla_z_buf, false);
+ CQM_CHECK_EQUAL_RET(
+ handle->dev_hdl, ret, CQM_SUCCESS,
+ return CQM_FAIL, CQM_ALLOC_FAIL(lvl_0_z_buf));
+
+ } else if (cla_table->max_buffer_size <=
+ (trunk_size * (trunk_size / sizeof(dma_addr_t)))) {
+ /* Level 1 CLA: Cla_y_buf is allocated during initialization,
+ * and cla_z_buf can be allocated dynamically
+ */
+ if (cqm_cla_xyz_lvl1(cqm_handle,
+ cla_table, trunk_size) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_cla_xyz_lvl1));
+ return CQM_FAIL;
+ }
+ } else if (cla_table->max_buffer_size <=
+ (trunk_size * (trunk_size / sizeof(dma_addr_t)) *
+ (trunk_size / sizeof(dma_addr_t)))) {
+ /* Level 2 CLA: Cla_x_buf is allocated during initialization,
+ * and cla_y_buf and cla_z_buf can be dynamically allocated
+ */
+ if (cqm_cla_xyz_lvl2(cqm_handle, cla_table, trunk_size) ==
+ CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_cla_xyz_lvl2));
+ return CQM_FAIL;
+ }
+ } else {
+ cqm_err(handle->dev_hdl, "Cla alloc: cla max_buffer_size 0x%x exceeds support range\n",
+ cla_table->max_buffer_size);
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+static void cqm_bat_entry_hash_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->hash_number *
+ capability->hash_basic_size;
+ cla_table->obj_size = capability->hash_basic_size;
+ cla_table->obj_num = capability->hash_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_qpc_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_handle_s *handle = (struct cqm_handle_s *)cqm_handle;
+ struct hifc_hwdev *hwdev_handle = handle->ex_handle;
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->qpc_number *
+ capability->qpc_basic_size;
+ cla_table->obj_size = capability->qpc_basic_size;
+ cla_table->obj_num = capability->qpc_number;
+ cla_table->alloc_static = capability->qpc_alloc_static;
+ cqm_info(hwdev_handle->dev_hdl, "Cla alloc: qpc alloc_static=%d\n",
+ cla_table->alloc_static);
+}
+
+static void cqm_bat_entry_mpt_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->mpt_number *
+ capability->mpt_basic_size;
+ cla_table->obj_size = capability->mpt_basic_size;
+ cla_table->obj_num = capability->mpt_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_scqc_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_handle_s *handle = (struct cqm_handle_s *)cqm_handle;
+ struct hifc_hwdev *hwdev_handle = handle->ex_handle;
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->scqc_number *
+ capability->scqc_basic_size;
+ cla_table->obj_size = capability->scqc_basic_size;
+ cla_table->obj_num = capability->scqc_number;
+ cla_table->alloc_static = capability->scqc_alloc_static;
+ cqm_info(hwdev_handle->dev_hdl, "Cla alloc: scqc alloc_static=%d\n",
+ cla_table->alloc_static);
+}
+
+static void cqm_bat_entry_srqc_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->srqc_number *
+ capability->srqc_basic_size;
+ cla_table->obj_size = capability->srqc_basic_size;
+ cla_table->obj_num = capability->srqc_number;
+ cla_table->alloc_static = false;
+}
+
+static void cqm_bat_entry_gid_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->max_buffer_size = capability->gid_number *
+ capability->gid_basic_size;
+ cla_table->trunk_order = (u32)cqm_shift(
+ ALIGN(
+ cla_table->max_buffer_size,
+ PAGE_SIZE) / PAGE_SIZE);
+ cla_table->obj_size = capability->gid_basic_size;
+ cla_table->obj_num = capability->gid_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_lun_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = CLA_TABLE_PAGE_ORDER;
+ cla_table->max_buffer_size = capability->lun_number *
+ capability->lun_basic_size;
+ cla_table->obj_size = capability->lun_basic_size;
+ cla_table->obj_num = capability->lun_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_taskmap_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = CQM_4K_PAGE_ORDER;
+ cla_table->max_buffer_size = capability->taskmap_number *
+ capability->taskmap_basic_size;
+ cla_table->obj_size = capability->taskmap_basic_size;
+ cla_table->obj_num = capability->taskmap_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_l3i_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = CLA_TABLE_PAGE_ORDER;
+ cla_table->max_buffer_size = capability->l3i_number *
+ capability->l3i_basic_size;
+ cla_table->obj_size = capability->l3i_basic_size;
+ cla_table->obj_num = capability->l3i_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_childc_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->childc_number *
+ capability->childc_basic_size;
+ cla_table->obj_size = capability->childc_basic_size;
+ cla_table->obj_num = capability->childc_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_timer_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = CQM_4K_PAGE_ORDER;
+ cla_table->max_buffer_size = capability->timer_number *
+ capability->timer_basic_size;
+ cla_table->obj_size = capability->timer_basic_size;
+ cla_table->obj_num = capability->timer_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_xid2cid_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->xid2cid_number *
+ capability->xid2cid_basic_size;
+ cla_table->obj_size = capability->xid2cid_basic_size;
+ cla_table->obj_num = capability->xid2cid_number;
+ cla_table->alloc_static = true;
+}
+
+static void cqm_bat_entry_reoder_init(void *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ void *cap)
+{
+ struct cqm_func_capability_s *capability =
+ (struct cqm_func_capability_s *)cap;
+
+ cla_table->trunk_order = capability->pagesize_reorder;
+ cla_table->max_buffer_size = capability->reorder_number *
+ capability->reorder_basic_size;
+ cla_table->obj_size = capability->reorder_basic_size;
+ cla_table->obj_num = capability->reorder_number;
+ cla_table->alloc_static = true;
+}
+
+struct cqm_cla_entry_init_s cqm_cla_entry_init_tbl[] = {
+ {CQM_BAT_ENTRY_T_HASH, cqm_bat_entry_hash_init},
+ {CQM_BAT_ENTRY_T_QPC, cqm_bat_entry_qpc_init},
+ {CQM_BAT_ENTRY_T_MPT, cqm_bat_entry_mpt_init},
+ {CQM_BAT_ENTRY_T_SCQC, cqm_bat_entry_scqc_init},
+ {CQM_BAT_ENTRY_T_SRQC, cqm_bat_entry_srqc_init},
+ {CQM_BAT_ENTRY_T_GID, cqm_bat_entry_gid_init},
+ {CQM_BAT_ENTRY_T_LUN, cqm_bat_entry_lun_init},
+ {CQM_BAT_ENTRY_T_TASKMAP, cqm_bat_entry_taskmap_init},
+ {CQM_BAT_ENTRY_T_L3I, cqm_bat_entry_l3i_init},
+ {CQM_BAT_ENTRY_T_CHILDC, cqm_bat_entry_childc_init},
+ {CQM_BAT_ENTRY_T_TIMER, cqm_bat_entry_timer_init},
+ {CQM_BAT_ENTRY_T_XID2CID, cqm_bat_entry_xid2cid_init},
+ {CQM_BAT_ENTRY_T_REORDER, cqm_bat_entry_reoder_init},
+};
+
+static struct cqm_cla_entry_init_s *cqm_get_cla_init_entry(
+ struct cqm_handle_s *cqm_handle,
+ u32 type)
+{
+ int i;
+ struct cqm_cla_entry_init_s *entry = NULL;
+
+ for (i = 0;
+ i < (sizeof(cqm_cla_entry_init_tbl) /
+ sizeof(struct cqm_cla_entry_init_s)); i++) {
+ entry = &cqm_cla_entry_init_tbl[i];
+ if (entry->type == type)
+ return entry;
+ }
+
+ return NULL;
+}
+
+void cqm_cla_init_entry(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ struct cqm_func_capability_s *capability)
+{
+ struct cqm_cla_entry_init_s *entry;
+
+ entry = cqm_get_cla_init_entry(cqm_handle, cla_table->type);
+ if (entry && entry->cqm_cla_init_handler)
+ entry->cqm_cla_init_handler(cqm_handle, cla_table, capability);
+}
+
+static s32 cqm_cla_fill_entry(struct cqm_handle_s *cqm_handle)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ s32 ret = CQM_FAIL;
+
+ /* After the allocation of CLA entry, fill in the BAT table */
+ cqm_bat_fill_cla(cqm_handle);
+
+ /* Notify the chip to refresh the BAT table */
+ ret = cqm_bat_update(cqm_handle);
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_update));
+ return CQM_FAIL;
+ }
+
+ cqm_info(handle->dev_hdl, "Timer start: func_type=%d, timer_enable=%u\n",
+ cqm_handle->func_attribute.func_type,
+ cqm_handle->func_capability.timer_enable);
+
+ if ((cqm_handle->func_attribute.func_type == CQM_PPF) &&
+ (cqm_handle->func_capability.timer_enable == CQM_TIMER_ENABLE)) {
+ /* After the timer resource is allocated,
+ * the timer needs to be enabled
+ */
+ cqm_info(handle->dev_hdl, "Timer start: hifc ppf timer start\n");
+ ret = hifc_ppf_tmr_start((void *)(cqm_handle->ex_handle));
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, "Timer start: hifc ppf timer start, ret=%d\n",
+ ret);
+ return CQM_FAIL;
+ }
+ }
+ return CQM_SUCCESS;
+}
+
+s32 cqm_cla_init(struct cqm_handle_s *cqm_handle)
+{
+ struct cqm_func_capability_s *capability = &cqm_handle->func_capability;
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ s32 inv_flag = 0;
+ u32 i = 0;
+ u32 j = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ cla_table->type = bat_table->bat_entry_type[i];
+
+ cqm_cla_init_entry(cqm_handle, cla_table, capability);
+
+ /* Allocate CLA entry space of all levels */
+ if ((cla_table->type >= CQM_BAT_ENTRY_T_HASH) &&
+ (cla_table->type <= CQM_BAT_ENTRY_T_REORDER)) {
+ /* Only needs to allocate timer resources for PPF,
+ * 8 wheels * 2k scales * 32B * func_num, for PF, there
+ * is no need to allocate resources for the timer, nor
+ * to fill in the structure of the timer entry in the
+ * BAT table.
+ */
+ if (!((cla_table->type == CQM_BAT_ENTRY_T_TIMER) &&
+ (cqm_handle->func_attribute.func_type
+ != CQM_PPF))) {
+ if (cqm_cla_xyz(cqm_handle, cla_table) ==
+ CQM_FAIL)
+ goto err;
+ }
+ }
+ mutex_init(&cla_table->lock);
+ }
+ if (cqm_cla_fill_entry(cqm_handle) == CQM_FAIL)
+ goto err;
+
+ return CQM_SUCCESS;
+
+err:
+ for (j = 0; j < i; j++) {
+ cla_table = &bat_table->entry[j];
+ if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) {
+ cqm_buf_free_cache_inv(cqm_handle,
+ &cla_table->cla_x_buf,
+ &inv_flag);
+ cqm_buf_free_cache_inv(cqm_handle,
+ &cla_table->cla_y_buf,
+ &inv_flag);
+ cqm_buf_free_cache_inv(cqm_handle,
+ &cla_table->cla_z_buf,
+ &inv_flag);
+ }
+ }
+
+ return CQM_FAIL;
+}
+
+void cqm_cla_uninit(struct cqm_handle_s *cqm_handle)
+{
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ s32 inv_flag = 0;
+ u32 i = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) {
+ cqm_buf_free_cache_inv(cqm_handle,
+ &cla_table->cla_x_buf,
+ &inv_flag);
+ cqm_buf_free_cache_inv(cqm_handle,
+ &cla_table->cla_y_buf,
+ &inv_flag);
+ cqm_buf_free_cache_inv(cqm_handle,
+ &cla_table->cla_z_buf,
+ &inv_flag);
+ }
+ }
+}
+
+s32 cqm_cla_update(struct cqm_handle_s *cqm_handle,
+ struct cqm_buf_list_s *buf_node_parent,
+ struct cqm_buf_list_s *buf_node_child,
+ u32 child_index, u8 cla_update_mode)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_cmd_buf_s *buf_in = NULL;
+ struct cqm_cla_update_cmd_s *cmd = NULL;
+ dma_addr_t pa = 0;
+ s32 ret = CQM_FAIL;
+ u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable;
+
+ buf_in = cqm_cmd_alloc((void *)(cqm_handle->ex_handle));
+ CQM_PTR_CHECK_RET(buf_in, return CQM_FAIL, CQM_ALLOC_FAIL(buf_in));
+ buf_in->size = sizeof(struct cqm_cla_update_cmd_s);
+
+ /* Fill the command format and convert to big endian */
+ cmd = (struct cqm_cla_update_cmd_s *)(buf_in->buf);
+
+ pa = buf_node_parent->pa + (child_index * sizeof(dma_addr_t));
+ cmd->gpa_h = CQM_ADDR_HI(pa);
+ cmd->gpa_l = CQM_ADDR_LW(pa);
+
+ pa = buf_node_child->pa;
+ cmd->value_h = CQM_ADDR_HI(pa);
+ cmd->value_l = CQM_ADDR_LW(pa);
+
+ cqm_dbg("Cla alloc: cqm_cla_update, gpa=0x%x 0x%x, value=0x%x 0x%x, cla_update_mode=0x%x\n",
+ cmd->gpa_h, cmd->gpa_l, cmd->value_h, cmd->value_l,
+ cla_update_mode);
+
+ /* CLA GPA check */
+ if (gpa_check_enable) {
+ switch (cla_update_mode) {
+ /* gpa[0]=1 means this GPA is valid */
+ case CQM_CLA_RECORD_NEW_GPA:
+ cmd->value_l |= 1;
+ break;
+ /* gpa[0]=0 means this GPA is valid */
+ case CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID:
+ case CQM_CLA_DEL_GPA_WITH_CACHE_INVALID:
+ cmd->value_l &= (~1);
+ break;
+ default:
+ cqm_err(handle->dev_hdl,
+ "Cla alloc: cqm_cla_update, cqm_cla_update, wrong cla_update_mode=%u\n",
+ cla_update_mode);
+ break;
+ }
+ }
+
+ cqm_swab32((u8 *)cmd, (sizeof(struct cqm_cla_update_cmd_s) >> 2));
+
+ ret = cqm_send_cmd_box((void *)(cqm_handle->ex_handle),
+ CQM_CMD_ACK_TYPE_CMDQ,
+ CQM_MOD_CQM, CQM_CMD_T_CLA_UPDATE,
+ buf_in, NULL, CQM_CMD_TIMEOUT);
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_send_cmd_box));
+ cqm_err(handle->dev_hdl,
+ "Cla alloc: cqm_cla_update, cqm_send_cmd_box_ret=%d\n",
+ ret);
+ cqm_err(handle->dev_hdl, "Cla alloc: cqm_cla_update, cla_update_cmd: 0x%x 0x%x 0x%x 0x%x\n",
+ cmd->gpa_h, cmd->gpa_l, cmd->value_h, cmd->value_l);
+ cqm_cmd_free((void *)(cqm_handle->ex_handle), buf_in);
+ return CQM_FAIL;
+ }
+
+ cqm_cmd_free((void *)(cqm_handle->ex_handle), buf_in);
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_cla_alloc - Allocate a CLA trunk page
+ * @cqm_handle: cqm handle
+ * @cla_table: cla handle
+ * @buf_node_parent: the parent node whose content is to be updated
+ * @buf_node_child: the child node whose content is to be allocated
+ * @child_index: child index
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_cla_alloc(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ struct cqm_buf_list_s *buf_node_parent,
+ struct cqm_buf_list_s *buf_node_child, u32 child_index)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ s32 ret = CQM_FAIL;
+
+ /* Allocate trunk page */
+ buf_node_child->va = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ cla_table->trunk_order);
+ CQM_PTR_CHECK_RET(buf_node_child->va, return CQM_FAIL,
+ CQM_ALLOC_FAIL(va));
+
+ /* pci mapping */
+ buf_node_child->pa =
+ pci_map_single(cqm_handle->dev, buf_node_child->va,
+ PAGE_SIZE << cla_table->trunk_order,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(cqm_handle->dev, buf_node_child->pa)) {
+ cqm_err(handle->dev_hdl, CQM_MAP_FAIL(buf_node_child->pa));
+ goto err1;
+ }
+
+ /* Notify the chip of trunk_pa and
+ * let it fill in the cla table entry
+ */
+ ret = cqm_cla_update(cqm_handle, buf_node_parent,
+ buf_node_child, child_index,
+ CQM_CLA_RECORD_NEW_GPA);
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_update));
+ goto err2;
+ }
+
+ return CQM_SUCCESS;
+
+err2:
+ pci_unmap_single(cqm_handle->dev, buf_node_child->pa,
+ PAGE_SIZE << cla_table->trunk_order,
+ PCI_DMA_BIDIRECTIONAL);
+err1:
+ free_pages((ulong)(buf_node_child->va), cla_table->trunk_order);
+ buf_node_child->va = NULL;
+ return CQM_FAIL;
+}
+
+void cqm_cla_free(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ struct cqm_buf_list_s *buf_node_parent,
+ struct cqm_buf_list_s *buf_node_child,
+ u32 child_index, u8 cla_update_mode)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ cqm_dbg("Cla free: cla_update_mode=%u\n", cla_update_mode);
+
+ if (cqm_cla_update(cqm_handle, buf_node_parent,
+ buf_node_child, child_index,
+ cla_update_mode) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_update));
+ return;
+ }
+
+ if (cla_update_mode == CQM_CLA_DEL_GPA_WITH_CACHE_INVALID) {
+ if (cqm_cla_cache_invalid(
+ cqm_handle, buf_node_child->pa,
+ PAGE_SIZE << cla_table->trunk_order) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_cla_cache_invalid));
+ return;
+ }
+ }
+
+ /* Unblock the pci mapping of the trunk page */
+ pci_unmap_single(cqm_handle->dev, buf_node_child->pa,
+ PAGE_SIZE << cla_table->trunk_order,
+ PCI_DMA_BIDIRECTIONAL);
+
+ /* Free trunk page */
+ free_pages((ulong)(buf_node_child->va), cla_table->trunk_order);
+ buf_node_child->va = NULL;
+}
+
+/**
+ * cqm_static_qpc_cla_get - When QPC is a static allocation, allocate the count
+ * of buffer from the index position in the cla table without lock
+ * @cqm_handle: cqm handle
+ * @cla_table: cla handle
+ * @index: the index of table
+ * @count: the count of buffer
+ * @pa: the physical address
+ * Return: the virtual address
+ */
+u8 *cqm_static_qpc_cla_get(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u32 index, u32 count, dma_addr_t *pa)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_y_buf = &cla_table->cla_y_buf;
+ struct cqm_buf_s *cla_z_buf = &cla_table->cla_z_buf;
+ struct cqm_buf_list_s *buf_node_z = NULL;
+ u32 x_index = 0;
+ u32 y_index = 0;
+ u32 z_index = 0;
+ u32 trunk_size = PAGE_SIZE << cla_table->trunk_order;
+ u8 *ret_addr = NULL;
+ u32 offset = 0;
+
+ if (cla_table->cla_lvl == CQM_CLA_LVL_0) {
+ offset = index * cla_table->obj_size;
+ ret_addr = (u8 *)(cla_z_buf->buf_list->va) + offset;
+ *pa = cla_z_buf->buf_list->pa + offset;
+ } else if (cla_table->cla_lvl == CQM_CLA_LVL_1) {
+ z_index = index & ((1 << (cla_table->z + 1)) - 1);
+ y_index = index >> (cla_table->z + 1);
+
+ if (y_index >= cla_z_buf->buf_number) {
+ cqm_err(handle->dev_hdl,
+ "Static qpc cla get: index exceeds buf_number, y_index %u, z_buf_number %u\n",
+ y_index, cla_z_buf->buf_number);
+ return NULL;
+ }
+ buf_node_z = &cla_z_buf->buf_list[y_index];
+ if (!buf_node_z->va) {
+ cqm_err(handle->dev_hdl, "Cla get: static qpc cla_z_buf[%u].va=NULL\n",
+ y_index);
+ return NULL;
+ }
+ buf_node_z->refcount += count;
+ offset = z_index * cla_table->obj_size;
+ ret_addr = (u8 *)(buf_node_z->va) + offset;
+ *pa = buf_node_z->pa + offset;
+ } else {
+ z_index = index & ((1 << (cla_table->z + 1)) - 1);
+ y_index = (index >> (cla_table->z + 1)) &
+ ((1 << (cla_table->y - cla_table->z)) - 1);
+ x_index = index >> (cla_table->y + 1);
+
+ if ((x_index >= cla_y_buf->buf_number) ||
+ ((x_index * (trunk_size / sizeof(dma_addr_t)) + y_index) >=
+ cla_z_buf->buf_number)) {
+ cqm_err(handle->dev_hdl,
+ "Static qpc cla get: index exceeds buf_number,x_index %u, y_index %u, y_buf_number %u, z_buf_number %u\n ",
+ x_index, y_index, cla_y_buf->buf_number,
+ cla_z_buf->buf_number);
+ return NULL;
+ }
+
+ buf_node_z = &(cla_z_buf->buf_list[x_index *
+ (trunk_size / sizeof(dma_addr_t)) + y_index]);
+ if (!buf_node_z->va) {
+ cqm_err(handle->dev_hdl, "Cla get: static qpc cla_z_buf.va=NULL\n");
+ return NULL;
+ }
+
+ buf_node_z->refcount += count;
+ offset = z_index * cla_table->obj_size;
+ ret_addr = (u8 *)(buf_node_z->va) + offset;
+ *pa = buf_node_z->pa + offset;
+ }
+
+ return ret_addr;
+}
+
+static s32 cqm_cla_get_level_two(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u32 index, u32 count,
+ dma_addr_t *pa, u8 **ret_addr)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_x_buf = &cla_table->cla_x_buf;
+ struct cqm_buf_s *cla_y_buf = &cla_table->cla_y_buf;
+ struct cqm_buf_s *cla_z_buf = &cla_table->cla_z_buf;
+ struct cqm_buf_list_s *buf_node_x = NULL;
+ struct cqm_buf_list_s *buf_node_y = NULL;
+ struct cqm_buf_list_s *buf_node_z = NULL;
+ u32 x_index = 0;
+ u32 y_index = 0;
+ u32 z_index = 0;
+ u32 trunk_size = PAGE_SIZE << cla_table->trunk_order;
+ u32 offset = 0;
+
+ z_index = index & ((1 << (cla_table->z + 1)) - 1);
+ y_index = (index >> (cla_table->z + 1)) &
+ ((1 << (cla_table->y - cla_table->z)) - 1);
+ x_index = index >> (cla_table->y + 1);
+
+ if ((x_index >= cla_y_buf->buf_number) ||
+ ((x_index * (trunk_size / sizeof(dma_addr_t)) + y_index) >=
+ cla_z_buf->buf_number)) {
+ cqm_err(handle->dev_hdl,
+ "Cla get: index exceeds buf_number, x_index %u, y_index %u, y_buf_number %u, z_buf_number %u\n",
+ x_index, y_index, cla_y_buf->buf_number,
+ cla_z_buf->buf_number);
+ return CQM_FAIL;
+ }
+
+ buf_node_x = cla_x_buf->buf_list;
+ buf_node_y = &cla_y_buf->buf_list[x_index];
+ buf_node_z = &(cla_z_buf->buf_list[x_index *
+ (trunk_size / sizeof(dma_addr_t)) + y_index]);
+
+ /* Y buf node does not exist, allocates y node page */
+ if (!buf_node_y->va) {
+ if (cqm_cla_alloc(
+ cqm_handle, cla_table,
+ buf_node_x, buf_node_y, x_index) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_cla_alloc));
+ return CQM_FAIL;
+ }
+ }
+
+ /* Z buf node does not exist, allocates z node page */
+ if (!buf_node_z->va) {
+ if (cqm_cla_alloc(cqm_handle,
+ cla_table,
+ buf_node_y,
+ buf_node_z,
+ y_index) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_cla_alloc));
+ if (buf_node_y->refcount == 0) {
+ /* Free y node, needs cache_invalid */
+ cqm_cla_free(
+ cqm_handle, cla_table,
+ buf_node_x, buf_node_y, x_index,
+ CQM_CLA_DEL_GPA_WITH_CACHE_INVALID);
+ }
+ return CQM_FAIL;
+ }
+
+ cqm_dbg("Cla get: 2L: y_refcount=0x%x\n", buf_node_y->refcount);
+ /* Y buf node's reference count should be +1 */
+ buf_node_y->refcount++;
+ }
+
+ cqm_dbg("Cla get: 2L: z_refcount=0x%x, count=0x%x\n",
+ buf_node_z->refcount, count);
+ buf_node_z->refcount += count;
+ offset = z_index * cla_table->obj_size;
+ *ret_addr = (u8 *)(buf_node_z->va) + offset;
+ *pa = buf_node_z->pa + offset;
+
+ return CQM_SUCCESS;
+}
+
+static s32 cqm_cla_get_level_one(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u32 index, u32 count, dma_addr_t *pa,
+ u8 **ret_addr)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_y_buf = &cla_table->cla_y_buf;
+ struct cqm_buf_s *cla_z_buf = &cla_table->cla_z_buf;
+ struct cqm_buf_list_s *buf_node_y = NULL;
+ struct cqm_buf_list_s *buf_node_z = NULL;
+ u32 y_index = 0;
+ u32 z_index = 0;
+ u32 offset = 0;
+
+ z_index = index & ((1 << (cla_table->z + 1)) - 1);
+ y_index = index >> (cla_table->z + 1);
+
+ if (y_index >= cla_z_buf->buf_number) {
+ cqm_err(handle->dev_hdl,
+ "Cla get: index exceeds buf_number, y_index %u, z_buf_number %u\n",
+ y_index, cla_z_buf->buf_number);
+ return CQM_FAIL;
+ }
+ buf_node_z = &cla_z_buf->buf_list[y_index];
+ buf_node_y = cla_y_buf->buf_list;
+
+ /* Z buf node does not exist, first allocate the page */
+ if (!buf_node_z->va) {
+ if (cqm_cla_alloc(cqm_handle,
+ cla_table,
+ buf_node_y,
+ buf_node_z,
+ y_index) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_cla_alloc));
+ cqm_err(handle->dev_hdl,
+ "Cla get: cla_table->type=%u\n",
+ cla_table->type);
+ return CQM_FAIL;
+ }
+ }
+
+ cqm_dbg("Cla get: 1L: z_refcount=0x%x, count=0x%x\n",
+ buf_node_z->refcount, count);
+ buf_node_z->refcount += count;
+ offset = z_index * cla_table->obj_size;
+ *ret_addr = (u8 *)(buf_node_z->va) + offset;
+ *pa = buf_node_z->pa + offset;
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_cla_get - Allocate the count of buffer from the index position in the
+ * cla table
+ * @cqm_handle: cqm handle
+ * @cla_table: cla table
+ * @index: the index of table
+ * @count: the count of buffer
+ * @pa: the physical address
+ * Return: the virtual address
+ */
+u8 *cqm_cla_get(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table, u32 index,
+ u32 count, dma_addr_t *pa)
+{
+ struct cqm_buf_s *cla_z_buf = &cla_table->cla_z_buf;
+ u8 *ret_addr = NULL;
+ u32 offset = 0;
+
+ mutex_lock(&cla_table->lock);
+ if (cla_table->cla_lvl == CQM_CLA_LVL_0) {
+ /* Level 0 CLA pages are statically allocated */
+ offset = index * cla_table->obj_size;
+ ret_addr = (u8 *)(cla_z_buf->buf_list->va) + offset;
+ *pa = cla_z_buf->buf_list->pa + offset;
+ } else if (cla_table->cla_lvl == CQM_CLA_LVL_1) {
+ if (cqm_cla_get_level_one(cqm_handle, cla_table,
+ index, count,
+ pa, &ret_addr) == CQM_FAIL) {
+ mutex_unlock(&cla_table->lock);
+ return NULL;
+ }
+ } else {
+ if (cqm_cla_get_level_two(cqm_handle,
+ cla_table,
+ index,
+ count,
+ pa,
+ &ret_addr) == CQM_FAIL) {
+ mutex_unlock(&cla_table->lock);
+ return NULL;
+ }
+ }
+
+ mutex_unlock(&cla_table->lock);
+ return ret_addr;
+}
+
+/**
+ * cqm_cla_put -Decrease the reference count of the trunk page, if it is reduced
+ * to 0, release the trunk page
+ * @cqm_handle: cqm handle
+ * @cla_table: cla table
+ * @index: the index of table
+ * @count: the count of buffer
+ */
+void cqm_cla_put(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ u32 index, u32 count)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_buf_s *cla_x_buf = &cla_table->cla_x_buf;
+ struct cqm_buf_s *cla_y_buf = &cla_table->cla_y_buf;
+ struct cqm_buf_s *cla_z_buf = &cla_table->cla_z_buf;
+ struct cqm_buf_list_s *buf_node_x = NULL;
+ struct cqm_buf_list_s *buf_node_y = NULL;
+ struct cqm_buf_list_s *buf_node_z = NULL;
+ u32 x_index = 0;
+ u32 y_index = 0;
+ u32 trunk_size = PAGE_SIZE << cla_table->trunk_order;
+
+ /* Buffer is statically allocated,
+ * no need to control the reference count
+ */
+ if (cla_table->alloc_static == true)
+ return;
+
+ mutex_lock(&cla_table->lock);
+
+ if (cla_table->cla_lvl == CQM_CLA_LVL_1) {
+ y_index = index >> (cla_table->z + 1);
+
+ if (y_index >= cla_z_buf->buf_number) {
+ cqm_err(handle->dev_hdl,
+ "Cla put: index exceeds buf_number, y_index %u, z_buf_number %u\n",
+ y_index, cla_z_buf->buf_number);
+ cqm_err(handle->dev_hdl,
+ "Cla put: cla_table->type=%u\n",
+ cla_table->type);
+ mutex_unlock(&cla_table->lock);
+ return;
+ }
+
+ buf_node_z = &cla_z_buf->buf_list[y_index];
+ buf_node_y = cla_y_buf->buf_list;
+
+ /* When the z node page reference count is 0,
+ * release the z node page
+ */
+ cqm_dbg("Cla put: 1L: z_refcount=0x%x, count=0x%x\n",
+ buf_node_z->refcount, count);
+ buf_node_z->refcount -= count;
+ if (buf_node_z->refcount == 0) {
+ /* Z node does not need cache invalid */
+ cqm_cla_free(cqm_handle, cla_table, buf_node_y,
+ buf_node_z, y_index,
+ CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID);
+ }
+ } else if (cla_table->cla_lvl == CQM_CLA_LVL_2) {
+ y_index = (index >> (cla_table->z + 1)) &
+ ((1 << (cla_table->y - cla_table->z)) - 1);
+ x_index = index >> (cla_table->y + 1);
+
+ if ((x_index >= cla_y_buf->buf_number) ||
+ ((x_index * (trunk_size / sizeof(dma_addr_t)) + y_index) >=
+ cla_z_buf->buf_number)) {
+ cqm_err(handle->dev_hdl,
+ "Cla put: index exceeds buf_number, x_index %u, y_index %u, y_buf_number %u, z_buf_number %u\n",
+ x_index, y_index, cla_y_buf->buf_number,
+ cla_z_buf->buf_number);
+ mutex_unlock(&cla_table->lock);
+ return;
+ }
+
+ buf_node_x = cla_x_buf->buf_list;
+ buf_node_y = &cla_y_buf->buf_list[x_index];
+ buf_node_z = &(cla_z_buf->buf_list[x_index *
+ (trunk_size / sizeof(dma_addr_t)) + y_index]);
+ cqm_dbg("Cla put: 2L: z_refcount=0x%x, count=0x%x\n",
+ buf_node_z->refcount, count);
+
+ /* When the z node page reference count is 0,
+ * release the z node page
+ */
+ buf_node_z->refcount -= count;
+ if (buf_node_z->refcount == 0) {
+ cqm_cla_free(cqm_handle, cla_table, buf_node_y,
+ buf_node_z, y_index,
+ CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID);
+
+ /* When the y node page reference count is 0,
+ * release the y node page
+ */
+ cqm_dbg("Cla put: 2L: y_refcount=0x%x\n",
+ buf_node_y->refcount);
+ buf_node_y->refcount--;
+ if (buf_node_y->refcount == 0) {
+ /* Y node needs cache invalid */
+ cqm_cla_free(
+ cqm_handle, cla_table, buf_node_x,
+ buf_node_y, x_index,
+ CQM_CLA_DEL_GPA_WITH_CACHE_INVALID);
+ }
+ }
+ }
+
+ mutex_unlock(&cla_table->lock);
+}
+
+/**
+ * cqm_cla_table_get - Find the CLA table structure corresponding to a BAT entry
+ * @bat_table: bat table
+ * @entry_type: entry type
+ * @count: the count of buffer
+ * Return: the CLA table
+ */
+struct cqm_cla_table_s *cqm_cla_table_get(struct cqm_bat_table_s *bat_table,
+ u32 entry_type)
+{
+ struct cqm_cla_table_s *cla_table = NULL;
+ u32 i = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ if (entry_type == cla_table->type)
+ return cla_table;
+ }
+
+ return NULL;
+}
+
+#define bitmap_section
+
+/**
+ * __cqm_bitmap_init - Initialize a bitmap
+ * @bitmap: cqm bitmap table
+ * Return: 0 - success, negative - failure
+ */
+s32 __cqm_bitmap_init(struct cqm_bitmap_s *bitmap)
+{
+ spin_lock_init(&bitmap->lock);
+
+ /* The max_num of bitmap is aligned by 8, and then shifted right by
+ * 3bits to get how many Bytes are needed
+ */
+ bitmap->table =
+ (ulong *)vmalloc((ALIGN(bitmap->max_num, 8) >> 3));
+ CQM_PTR_CHECK_RET(bitmap->table, return CQM_FAIL,
+ CQM_ALLOC_FAIL(bitmap->table));
+ memset(bitmap->table, 0, (ALIGN(bitmap->max_num, 8) >> 3));
+
+ return CQM_SUCCESS;
+}
+
+static s32 cqm_bitmap_init_by_type(struct cqm_handle_s *cqm_handle,
+ struct cqm_cla_table_s *cla_table,
+ struct cqm_bitmap_s *bitmap)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_func_capability_s *capability = &cqm_handle->func_capability;
+ s32 ret = CQM_SUCCESS;
+
+ switch (cla_table->type) {
+ case CQM_BAT_ENTRY_T_QPC:
+ bitmap->max_num = capability->qpc_number;
+ bitmap->reserved_top = capability->qpc_reserved;
+ bitmap->last = capability->qpc_reserved;
+ cqm_info(handle->dev_hdl, "Bitmap init: cla_table_type=%u, max_num=0x%x\n",
+ cla_table->type, bitmap->max_num);
+ ret = __cqm_bitmap_init(bitmap);
+ break;
+ case CQM_BAT_ENTRY_T_MPT:
+ bitmap->max_num = capability->mpt_number;
+ bitmap->reserved_top = capability->mpt_reserved;
+ bitmap->last = capability->mpt_reserved;
+ cqm_info(handle->dev_hdl, "Bitmap init: cla_table_type=%u, max_num=0x%x\n",
+ cla_table->type, bitmap->max_num);
+ ret = __cqm_bitmap_init(bitmap);
+ break;
+ case CQM_BAT_ENTRY_T_SCQC:
+ bitmap->max_num = capability->scqc_number;
+ bitmap->reserved_top = capability->scq_reserved;
+ bitmap->last = capability->scq_reserved;
+ cqm_info(handle->dev_hdl, "Bitmap init: cla_table_type=%u, max_num=0x%x\n",
+ cla_table->type, bitmap->max_num);
+ ret = __cqm_bitmap_init(bitmap);
+ break;
+ case CQM_BAT_ENTRY_T_SRQC:
+ bitmap->max_num = capability->srqc_number;
+ bitmap->reserved_top = 0;
+ bitmap->last = 0;
+ cqm_info(handle->dev_hdl, "Bitmap init: cla_table_type=%u, max_num=0x%x\n",
+ cla_table->type, bitmap->max_num);
+ ret = __cqm_bitmap_init(bitmap);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * cqm_bitmap_init - Initialize a bitmap
+ * @cqm_handle: cqm handle
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_bitmap_init(struct cqm_handle_s *cqm_handle)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_bitmap_s *bitmap = NULL;
+ u32 i = 0;
+ s32 ret = CQM_SUCCESS;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ if (cla_table->obj_num == 0) {
+ cqm_info(handle->dev_hdl, "Cla alloc: cla_type %u, obj_num=0, don't init bitmap\n",
+ cla_table->type);
+ continue;
+ }
+
+ bitmap = &cla_table->bitmap;
+ ret = cqm_bitmap_init_by_type(cqm_handle, cla_table, bitmap);
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl, "Bitmap init: failed to init cla_table_type=%u, obj_num=0x%x\n",
+ cla_table->type, cla_table->obj_num);
+ goto err;
+ }
+ }
+
+ return CQM_SUCCESS;
+
+err:
+ cqm_bitmap_uninit(cqm_handle);
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_bitmap_uninit - Uninitialize a bitmap
+ * @cqm_handle: cqm handle
+ */
+void cqm_bitmap_uninit(struct cqm_handle_s *cqm_handle)
+{
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_bitmap_s *bitmap = NULL;
+ u32 i = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ bitmap = &cla_table->bitmap;
+ if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) {
+ if (bitmap->table) {
+ vfree(bitmap->table);
+ bitmap->table = NULL;
+ }
+ }
+ }
+}
+
+/**
+ * cqm_bitmap_check_range - Starting from begin, check whether count bits are
+ * free in the table, required: 1. This set of bits cannot cross step, 2. This
+ * group of bits must be 0
+ * @table: bitmap table
+ * @step: steps
+ * @max_num: max num
+ * @begin: begin position
+ * @count: the count of bit to check
+ * Return: If check valid return begin position
+ */
+u32 cqm_bitmap_check_range(const ulong *table, u32 step,
+ u32 max_num, u32 begin, u32 count)
+{
+ u32 i = 0;
+ u32 end = (begin + (count - 1));
+
+ /* Single bit is not checked */
+ if (count == 1)
+ return begin;
+
+ /* End is out of bounds */
+ if (end >= max_num)
+ return max_num;
+
+ /* Bit check, if there is a bit other than 0, return next bit */
+ for (i = (begin + 1); i <= end; i++) {
+ if (test_bit((s32)i, table))
+ return i + 1;
+ }
+
+ /* Check if it is in a different step */
+ if ((begin & (~(step - 1))) != (end & (~(step - 1))))
+ return (end & (~(step - 1)));
+
+ /* If check pass, return begin position */
+ return begin;
+}
+
+static void cqm_bitmap_set_bit(struct cqm_bitmap_s *bitmap, u32 index,
+ u32 max_num, u32 count, bool update_last,
+ ulong *table)
+{
+ u32 i;
+
+ /* Set 1 to the found bit and reset last */
+ if (index < max_num) {
+ for (i = index; i < (index + count); i++)
+ set_bit(i, table);
+
+ if (update_last) {
+ bitmap->last = (index + count);
+ if (bitmap->last >= bitmap->max_num)
+ bitmap->last = bitmap->reserved_top;
+ }
+ }
+}
+
+/**
+ * cqm_bitmap_alloc - Allocate a bitmap index, 0 and 1 should not be used, Scan
+ * back from the place where you last applied, and needs to support the
+ * application of a series of consecutive indexes, and should not to cross trunk
+ * @table: bitmap table
+ * @step: steps
+ * @count: the count of bit to check
+ * @update_last: update last
+ * Return: Success - return the index, failure - return the max
+ */
+u32 cqm_bitmap_alloc(struct cqm_bitmap_s *bitmap, u32 step, u32 count,
+ bool update_last)
+{
+ u32 index = 0;
+ u32 max_num = bitmap->max_num;
+ u32 last = bitmap->last;
+ ulong *table = bitmap->table;
+
+ spin_lock(&bitmap->lock);
+
+ /* Search for a free bit from the last position */
+ do {
+ index = find_next_zero_bit(table, max_num, last);
+ if (index < max_num) {
+ last = cqm_bitmap_check_range(table, step,
+ max_num, index, count);
+ } else {
+ break;
+ }
+ } while (last != index);
+
+ /* The above search failed, search for a free bit from the beginning */
+ if (index >= max_num) {
+ last = bitmap->reserved_top;
+ do {
+ index = find_next_zero_bit(table, max_num, last);
+ if (index < max_num) {
+ last = cqm_bitmap_check_range(table, step,
+ max_num,
+ index, count);
+ } else {
+ break;
+ }
+ } while (last != index);
+ }
+ cqm_bitmap_set_bit(bitmap, index, max_num, count, update_last, table);
+ spin_unlock(&bitmap->lock);
+ return index;
+}
+
+/**
+ * cqm_bitmap_alloc_reserved - Allocate the reserve bit according to index
+ * @bitmap: bitmap table
+ * @count: count
+ * @index: the index of bitmap
+ * Return: Success - return the index, failure - return the max
+ */
+u32 cqm_bitmap_alloc_reserved(struct cqm_bitmap_s *bitmap, u32 count, u32 index)
+{
+ ulong *table = bitmap->table;
+ u32 ret_index = CQM_INDEX_INVALID;
+
+ if ((index >= bitmap->reserved_top) || (index >= bitmap->max_num) ||
+ (count != 1)) {
+ return CQM_INDEX_INVALID;
+ }
+
+ spin_lock(&bitmap->lock);
+
+ if (test_bit(index, table)) {
+ ret_index = CQM_INDEX_INVALID;
+ } else {
+ set_bit(index, table);
+ ret_index = index;
+ }
+
+ spin_unlock(&bitmap->lock);
+ return ret_index;
+}
+
+/**
+ * cqm_bitmap_free - Release a bitmap index
+ * @bitmap: bitmap table
+ * @index: the index of bitmap
+ * @count: count
+ */
+void cqm_bitmap_free(struct cqm_bitmap_s *bitmap, u32 index, u32 count)
+{
+ ulong i = 0;
+
+ spin_lock(&bitmap->lock);
+
+ for (i = index; i < (index + count); i++)
+ clear_bit((s32)i, bitmap->table);
+
+ spin_unlock(&bitmap->lock);
+}
+
+#define obj_table_section
+
+/**
+ * _cqm_object_table_init - Initialize a table of object and index
+ * @cqm_handle: cqm handle
+ * Return: 0 - success, negative - failure
+ */
+s32 __cqm_object_table_init(struct cqm_object_table_s *obj_table)
+{
+ rwlock_init(&obj_table->lock);
+
+ obj_table->table = (struct cqm_object_s **)vmalloc(obj_table->max_num *
+ sizeof(void *));
+ CQM_PTR_CHECK_RET(obj_table->table, return CQM_FAIL,
+ CQM_ALLOC_FAIL(table));
+ memset(obj_table->table, 0, obj_table->max_num * sizeof(void *));
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_object_table_init - Initialize the association table of object and index
+ * @cqm_handle: cqm handle
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_object_table_init(struct cqm_handle_s *cqm_handle)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_func_capability_s *capability = &cqm_handle->func_capability;
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_object_table_s *obj_table = NULL;
+ s32 ret = CQM_SUCCESS;
+ u32 i = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ if (cla_table->obj_num == 0) {
+ cqm_info(handle->dev_hdl,
+ "Obj table init: cla_table_type %u, obj_num=0, don't init obj table\n",
+ cla_table->type);
+ continue;
+ }
+
+ obj_table = &cla_table->obj_table;
+
+ switch (cla_table->type) {
+ case CQM_BAT_ENTRY_T_QPC:
+ obj_table->max_num = capability->qpc_number;
+ ret = __cqm_object_table_init(obj_table);
+ break;
+ case CQM_BAT_ENTRY_T_MPT:
+ obj_table->max_num = capability->mpt_number;
+ ret = __cqm_object_table_init(obj_table);
+ break;
+ case CQM_BAT_ENTRY_T_SCQC:
+ obj_table->max_num = capability->scqc_number;
+ ret = __cqm_object_table_init(obj_table);
+ break;
+ case CQM_BAT_ENTRY_T_SRQC:
+ obj_table->max_num = capability->srqc_number;
+ ret = __cqm_object_table_init(obj_table);
+ break;
+ default:
+ break;
+ }
+
+ if (ret != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl,
+ "Obj table init: failed to init cla_table_type=%u, obj_num=0x%x\n",
+ cla_table->type, cla_table->obj_num);
+ goto err;
+ }
+ }
+
+ return CQM_SUCCESS;
+
+err:
+ cqm_object_table_uninit(cqm_handle);
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_object_table_uninit - Deinitialize the association table of object and
+ * index
+ * @cqm_handle: cqm handle
+ */
+void cqm_object_table_uninit(struct cqm_handle_s *cqm_handle)
+{
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_object_table_s *obj_table = NULL;
+ u32 i = 0;
+
+ for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
+ cla_table = &bat_table->entry[i];
+ obj_table = &cla_table->obj_table;
+ if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) {
+ if (obj_table->table) {
+ vfree(obj_table->table);
+ obj_table->table = NULL;
+ }
+ }
+ }
+}
+
+/**
+ * cqm_object_table_insert - Insert an object, turn off the soft interrupt
+ * @cqm_handle: cqm handle
+ * @object_table: object table
+ * @index: the index of table
+ * @obj: the object to insert
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_object_table_insert(struct cqm_handle_s *cqm_handle,
+ struct cqm_object_table_s *object_table, u32 index,
+ struct cqm_object_s *obj)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ if (index >= object_table->max_num) {
+ cqm_err(handle->dev_hdl, "Obj table insert: index 0x%x exceeds max_num 0x%x\n",
+ index, object_table->max_num);
+ return CQM_FAIL;
+ }
+
+ write_lock(&object_table->lock);
+
+ if (!object_table->table[index]) {
+ object_table->table[index] = obj;
+ write_unlock(&object_table->lock);
+ return CQM_SUCCESS;
+ }
+ write_unlock(&object_table->lock);
+ cqm_err(handle->dev_hdl, "Obj table insert: object_table->table[0x%x] has been inserted\n",
+ index);
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_object_table_remove - remove an object
+ * @cqm_handle: cqm handle
+ * @object_table: object table
+ * @index: the index of table
+ * @obj: the object to remove
+ * Return: 0 - success, negative - failure
+ */
+void cqm_object_table_remove(struct cqm_handle_s *cqm_handle,
+ struct cqm_object_table_s *object_table,
+ u32 index, const struct cqm_object_s *obj)
+{
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ if (index >= object_table->max_num) {
+ cqm_err(handle->dev_hdl, "Obj table remove: index 0x%x exceeds max_num 0x%x\n",
+ index, object_table->max_num);
+ return;
+ }
+
+ write_lock(&object_table->lock);
+
+ if ((object_table->table[index]) &&
+ (object_table->table[index] == obj)) {
+ object_table->table[index] = NULL;
+ } else {
+ cqm_err(handle->dev_hdl, "Obj table remove: object_table->table[0x%x] has been removed\n",
+ index);
+ }
+
+ write_unlock(&object_table->lock);
+}
+
+/**
+ * cqm_srq_used_rq_delete - Delete rq in TOE SRQ mode
+ * @object: cqm object
+ */
+void cqm_srq_used_rq_delete(struct cqm_object_s *object)
+{
+ struct cqm_queue_s *common = container_of(object, struct cqm_queue_s,
+ object);
+ struct cqm_nonrdma_qinfo_s *qinfo = container_of(
+ common,
+ struct cqm_nonrdma_qinfo_s,
+ common);
+ u32 link_wqe_offset = qinfo->wqe_per_buf * qinfo->wqe_size;
+ struct cqm_srq_linkwqe_s *srq_link_wqe = NULL;
+ dma_addr_t addr;
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ (common->object.cqm_handle);
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+
+ /* The current SRQ solution does not support the case where RQ
+ * initialization without container, which may cause error when RQ
+ * resources are released. So RQ initializes with only one container,
+ * and releases only one contaienr when resourced are released.
+ */
+ CQM_PTR_CHECK_NO_RET(
+ common->head_container, "Rq del: rq has no contianer to release\n",
+ return);
+
+ /* Get current container pa from link wqe, and ummap it */
+ srq_link_wqe = (struct cqm_srq_linkwqe_s *)(common->head_container +
+ link_wqe_offset);
+ /* Convert only the big endian of the wqe part of the link */
+ cqm_swab32((u8 *)(srq_link_wqe), sizeof(struct cqm_linkwqe_s) >> 2);
+
+ addr = CQM_ADDR_COMBINE(srq_link_wqe->current_buffer_gpa_h,
+ srq_link_wqe->current_buffer_gpa_l);
+ if (addr == 0) {
+ cqm_err(handle->dev_hdl, "Rq del: buffer physical addr is null\n");
+ return;
+ }
+ pci_unmap_single(cqm_handle->dev, addr, qinfo->container_size,
+ PCI_DMA_BIDIRECTIONAL);
+
+ /* Get current container va from link wqe, and free it */
+ addr = CQM_ADDR_COMBINE(srq_link_wqe->current_buffer_addr_h,
+ srq_link_wqe->current_buffer_addr_l);
+ if (addr == 0) {
+ cqm_err(handle->dev_hdl, "Rq del: buffer virtual addr is null\n");
+ return;
+ }
+ kfree((void *)addr);
+}
+
+#define obj_intern_if_section
+
+/**
+ * cqm_qpc_mpt_bitmap_alloc - Apply index from bitmap when creating qpc or mpt
+ * @object: cqm object
+ * @cla_table: cla table
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_qpc_mpt_bitmap_alloc(struct cqm_object_s *object,
+ struct cqm_cla_table_s *cla_table)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_qpc_mpt_s *common = container_of(object,
+ struct cqm_qpc_mpt_s,
+ object);
+ struct cqm_qpc_mpt_info_s *qpc_mpt_info =
+ container_of(
+ common,
+ struct cqm_qpc_mpt_info_s,
+ common);
+ struct cqm_bitmap_s *bitmap = &cla_table->bitmap;
+ u32 index = 0;
+ u32 count = 0;
+
+ count = (ALIGN(object->object_size, cla_table->obj_size)) /
+ cla_table->obj_size;
+ qpc_mpt_info->index_count = count;
+
+ if (qpc_mpt_info->common.xid == CQM_INDEX_INVALID) {
+ /* Allocate index normally */
+ index = cqm_bitmap_alloc(
+ bitmap,
+ 1 << (cla_table->z + 1),
+ count,
+ cqm_handle->func_capability.xid_alloc_mode);
+ if (index < bitmap->max_num) {
+ qpc_mpt_info->common.xid = index;
+ } else {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_bitmap_alloc));
+ return CQM_FAIL;
+ }
+ } else {
+ /* Allocate reserved index */
+ index = cqm_bitmap_alloc_reserved(
+ bitmap, count,
+ qpc_mpt_info->common.xid);
+ if (index != qpc_mpt_info->common.xid) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_bitmap_alloc_reserved));
+ return CQM_FAIL;
+ }
+ }
+
+ return CQM_SUCCESS;
+}
+
+static struct cqm_cla_table_s *cqm_qpc_mpt_prepare_cla_table(
+ struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+
+ struct cqm_cla_table_s *cla_table = NULL;
+
+ /* Get the corresponding cla table */
+ if (object->object_type == CQM_OBJECT_SERVICE_CTX) {
+ cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_QPC);
+ } else {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->object_type));
+ return NULL;
+ }
+
+ CQM_PTR_CHECK_RET(cla_table, return NULL,
+ CQM_FUNCTION_FAIL(cqm_cla_table_get));
+
+ /* Allocate index for bitmap */
+ if (cqm_qpc_mpt_bitmap_alloc(object, cla_table) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_qpc_mpt_bitmap_alloc));
+ return NULL;
+ }
+
+ return cla_table;
+}
+
+/**
+ * cqm_qpc_mpt_create - Create qpc or mpt
+ * @object: cqm object
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_qpc_mpt_create(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_qpc_mpt_s *common =
+ container_of(object, struct cqm_qpc_mpt_s, object);
+ struct cqm_qpc_mpt_info_s *qpc_mpt_info =
+ container_of(common, struct cqm_qpc_mpt_info_s, common);
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_bitmap_s *bitmap = NULL;
+ struct cqm_object_table_s *object_table = NULL;
+ u32 index = 0;
+ u32 count = 0;
+
+ cla_table = cqm_qpc_mpt_prepare_cla_table(object);
+ CQM_PTR_CHECK_RET(cla_table, return CQM_FAIL,
+ CQM_FUNCTION_FAIL(cqm_qpc_mpt_prepare_cla_table));
+
+ bitmap = &cla_table->bitmap;
+ index = qpc_mpt_info->common.xid;
+ count = qpc_mpt_info->index_count;
+
+ /* Find the trunk page from BAT/CLA and allocate the buffer, the
+ * business needs to ensure that the released buffer has been cleared
+ */
+ if (cla_table->alloc_static == true) {
+ qpc_mpt_info->common.vaddr =
+ cqm_static_qpc_cla_get(cqm_handle, cla_table,
+ index, count, &common->paddr);
+ } else {
+ qpc_mpt_info->common.vaddr =
+ cqm_cla_get(cqm_handle, cla_table,
+ index, count, &common->paddr);
+ }
+ if (!qpc_mpt_info->common.vaddr) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_get));
+ cqm_err(handle->dev_hdl,
+ "Qpc mpt init: qpc mpt vaddr is null, cla_table->alloc_static=%d\n",
+ cla_table->alloc_static);
+ goto err1;
+ }
+
+ /* Associate index with object, FC executes in interrupt context */
+ object_table = &cla_table->obj_table;
+
+ if (cqm_object_table_insert(cqm_handle, object_table, index, object) !=
+ CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_object_table_insert));
+ goto err2;
+ }
+
+ return CQM_SUCCESS;
+
+err2:
+ cqm_cla_put(cqm_handle, cla_table, index, count);
+err1:
+ cqm_bitmap_free(bitmap, index, count);
+ return CQM_FAIL;
+}
+
+/**
+ * cqm_qpc_mpt_delete - Delete qpc or mpt
+ * @object: cqm object
+ */
+void cqm_qpc_mpt_delete(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_qpc_mpt_s *common = container_of(object,
+ struct cqm_qpc_mpt_s,
+ object);
+ struct cqm_qpc_mpt_info_s *qpc_mpt_info = container_of(
+ common,
+ struct cqm_qpc_mpt_info_s,
+ common);
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_bitmap_s *bitmap = NULL;
+ struct cqm_object_table_s *object_table = NULL;
+ u32 index = qpc_mpt_info->common.xid;
+ u32 count = qpc_mpt_info->index_count;
+
+ /* Find the response cla table */
+ atomic_inc(&cqm_handle->ex_handle->hw_stats.cqm_stats.cqm_qpc_mpt_delete_cnt);
+
+ if (object->object_type == CQM_OBJECT_SERVICE_CTX) {
+ cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_QPC);
+ } else {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->object_type));
+ return;
+ }
+
+ CQM_PTR_CHECK_NO_RET(
+ cla_table, CQM_FUNCTION_FAIL(cqm_cla_table_get), return);
+
+ /* Disassociate index with object */
+ object_table = &cla_table->obj_table;
+
+ cqm_object_table_remove(cqm_handle, object_table, index, object);
+
+ /* Wait for the completion and ensure that all references to the QPC
+ * are completed
+ */
+ if (atomic_dec_and_test(&object->refcount)) {
+ complete(&object->free);
+ } else {
+ cqm_err(handle->dev_hdl,
+ "Qpc mpt del: object is referred by others, has to wait for completion\n");
+ }
+
+ /* The QPC static allocation needs to be non-blocking, and the service
+ * guarantees that the QPC is completed when the QPC is deleted
+ */
+ if (cla_table->alloc_static == false)
+ wait_for_completion(&object->free);
+ /* Free qpc buffer */
+ cqm_cla_put(cqm_handle, cla_table, index, count);
+
+ /* Free index into bitmap */
+ bitmap = &cla_table->bitmap;
+ cqm_bitmap_free(bitmap, index, count);
+}
+
+/**
+ * cqm_linkwqe_fill - Fill link wqe for non RDMA queue buffer
+ * @buf: cqm buffer
+ * @wqe_per_buf: not include link wqe
+ * @wqe_size: wqe size
+ * @wqe_number: not include link wqe
+ * @tail: true linkwqe must be at the tail, false linkwqe may not be at the tail
+ * @link_mode: link wqe mode
+ */
+void cqm_linkwqe_fill(struct cqm_buf_s *buf,
+ u32 wqe_per_buf,
+ u32 wqe_size,
+ u32 wqe_number,
+ bool tail,
+ u8 link_mode)
+{
+ struct cqm_linkwqe_s *wqe = NULL;
+ struct cqm_linkwqe_128b_s *linkwqe = NULL;
+ u8 *va = NULL;
+ u32 i = 0;
+ dma_addr_t addr;
+
+ /* Except for the last buffer, the linkwqe of other buffers is directly
+ * filled to the tail
+ */
+ for (i = 0; i < buf->buf_number; i++) {
+ va = (u8 *)(buf->buf_list[i].va);
+
+ if (i != (buf->buf_number - 1)) {
+ wqe = (struct cqm_linkwqe_s *)(va + (u32)(wqe_size *
+ wqe_per_buf));
+ wqe->wf = CQM_WQE_WF_LINK;
+ wqe->ctrlsl = CQM_LINK_WQE_CTRLSL_VALUE;
+ wqe->lp = CQM_LINK_WQE_LP_INVALID;
+ /* The Obit of valid link wqe needs to be set to 1, and
+ * each service needs to confirm that o-bit=1 means
+ * valid, o-bit=0 means invalid
+ */
+ wqe->o = CQM_LINK_WQE_OWNER_VALID;
+ addr = buf->buf_list[(u32)(i + 1)].pa;
+ wqe->next_page_gpa_h = CQM_ADDR_HI(addr);
+ wqe->next_page_gpa_l = CQM_ADDR_LW(addr);
+ } else {
+ /* The last buffer of Linkwqe must fill specially */
+ if (tail == true) {
+ /* Must be filled at the end of the page */
+ wqe = (struct cqm_linkwqe_s *)(va +
+ (u32)(wqe_size * wqe_per_buf));
+ } else {
+ /* The last linkwqe is filled immediately after
+ * the last wqe
+ */
+ wqe = (struct cqm_linkwqe_s *)
+ (va + (u32)(wqe_size *
+ (wqe_number - wqe_per_buf *
+ (buf->buf_number - 1))));
+ }
+ wqe->wf = CQM_WQE_WF_LINK;
+ wqe->ctrlsl = CQM_LINK_WQE_CTRLSL_VALUE;
+
+ /* In link mode, the last link wqe is invalid, In ring
+ * mode, the last link wqe is valid, pointing to the
+ * home page, and lp is set
+ */
+ if (link_mode == CQM_QUEUE_LINK_MODE) {
+ wqe->o = CQM_LINK_WQE_OWNER_INVALID;
+ } else {
+ /* The lp field of the last link_wqe is filled
+ * with 1,indicating that the o-bit is flipped
+ * from here
+ */
+ wqe->lp = CQM_LINK_WQE_LP_VALID;
+ wqe->o = CQM_LINK_WQE_OWNER_VALID;
+ addr = buf->buf_list[0].pa;
+ wqe->next_page_gpa_h = CQM_ADDR_HI(addr);
+ wqe->next_page_gpa_l = CQM_ADDR_LW(addr);
+ }
+ }
+
+ if (wqe_size == 128) {
+ /* The 128B wqe before and after 64B have obit need to be
+ * assigned, For IFOE, 63th penultimate bit of last 64B is
+ * obit, for TOE, 157th penultimate bit of last 64B is obit
+ */
+ linkwqe = (struct cqm_linkwqe_128b_s *)wqe;
+ linkwqe->second_64b.third_16B.bs.toe_o =
+ CQM_LINK_WQE_OWNER_VALID;
+ linkwqe->second_64b.forth_16B.bs.ifoe_o =
+ CQM_LINK_WQE_OWNER_VALID;
+
+ /* big endian conversion */
+ cqm_swab32((u8 *)wqe,
+ sizeof(struct cqm_linkwqe_128b_s) >> 2);
+ } else {
+ /* big endian conversion */
+ cqm_swab32((u8 *)wqe,
+ sizeof(struct cqm_linkwqe_s) >> 2);
+ }
+ }
+}
+
+static s32 cqm_nonrdma_queue_ctx_create_srq(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_queue_s *common = container_of(object,
+ struct cqm_queue_s, object);
+ struct cqm_nonrdma_qinfo_s *qinfo = container_of(
+ common,
+ struct cqm_nonrdma_qinfo_s,
+ common);
+ s32 shift = 0;
+
+ shift = cqm_shift(qinfo->q_ctx_size);
+ common->q_ctx_vaddr = (u8 *)cqm_kmalloc_align(
+ qinfo->q_ctx_size,
+ GFP_KERNEL | __GFP_ZERO,
+ (u16)shift);
+ if (!common->q_ctx_vaddr) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(q_ctx_vaddr));
+ return CQM_FAIL;
+ }
+
+ common->q_ctx_paddr =
+ pci_map_single(cqm_handle->dev, common->q_ctx_vaddr,
+ qinfo->q_ctx_size, PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(cqm_handle->dev, common->q_ctx_paddr)) {
+ cqm_err(handle->dev_hdl, CQM_MAP_FAIL(q_ctx_vaddr));
+ cqm_kfree_align(common->q_ctx_vaddr);
+ common->q_ctx_vaddr = NULL;
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+static s32 cqm_nonrdma_queue_ctx_create_scq(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_queue_s *common = container_of(object,
+ struct cqm_queue_s,
+ object);
+ struct cqm_nonrdma_qinfo_s *qinfo = container_of(
+ common,
+ struct cqm_nonrdma_qinfo_s,
+ common);
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_bitmap_s *bitmap = NULL;
+ struct cqm_object_table_s *object_table = NULL;
+
+ /* Find the corresponding cla table */
+ cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_SCQC);
+ if (!cla_table) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_table_get));
+ return CQM_FAIL;
+ }
+
+ /* Allocate index for bitmap */
+ bitmap = &cla_table->bitmap;
+ qinfo->index_count = (ALIGN(qinfo->q_ctx_size, cla_table->obj_size)) /
+ cla_table->obj_size;
+ qinfo->common.index = cqm_bitmap_alloc(bitmap, 1 << (cla_table->z + 1),
+ qinfo->index_count, cqm_handle->func_capability.xid_alloc_mode);
+ if (qinfo->common.index >= bitmap->max_num) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bitmap_alloc));
+ return CQM_FAIL;
+ }
+
+ /* Find the trunk page from BAT/CLA and allocate buffer */
+ common->q_ctx_vaddr = cqm_cla_get(cqm_handle, cla_table,
+ qinfo->common.index,
+ qinfo->index_count,
+ &common->q_ctx_paddr);
+ if (!common->q_ctx_vaddr) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_get));
+ cqm_bitmap_free(bitmap, qinfo->common.index,
+ qinfo->index_count);
+ return CQM_FAIL;
+ }
+
+ /* Associate index with object */
+ object_table = &cla_table->obj_table;
+
+ if (cqm_object_table_insert(
+ cqm_handle, object_table,
+ qinfo->common.index, object) != CQM_SUCCESS) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_object_table_insert));
+ cqm_cla_put(cqm_handle, cla_table, qinfo->common.index,
+ qinfo->index_count);
+ cqm_bitmap_free(bitmap, qinfo->common.index,
+ qinfo->index_count);
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+s32 cqm_nonrdma_queue_ctx_create(struct cqm_object_s *object)
+{
+ if (object->object_type == CQM_OBJECT_NONRDMA_SRQ)
+ return cqm_nonrdma_queue_ctx_create_srq(object);
+ else if (object->object_type == CQM_OBJECT_NONRDMA_SCQ)
+ return cqm_nonrdma_queue_ctx_create_scq(object);
+
+ return CQM_SUCCESS;
+}
+
+#define CQM_NORDMA_CHECK_WEQ_NUMBER(number) \
+ (((number) < CQM_CQ_DEPTH_MIN) || ((number) > CQM_CQ_DEPTH_MAX))
+
+/**
+ * cqm_nonrdma_queue_create - Create queue for non RDMA service
+ * @buf: cqm object
+ * Return: 0 - success, negative - failure
+ */
+s32 cqm_nonrdma_queue_create(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_service_s *service = &cqm_handle->service;
+ struct cqm_queue_s *common = container_of(object,
+ struct cqm_queue_s,
+ object);
+ struct cqm_nonrdma_qinfo_s *qinfo = container_of(
+ common,
+ struct cqm_nonrdma_qinfo_s,
+ common);
+ struct cqm_buf_s *q_room_buf = &common->q_room_buf_1;
+ u32 wqe_number = qinfo->common.object.object_size;
+ u32 wqe_size = qinfo->wqe_size;
+ u32 order = service->buf_order;
+ u32 buf_number = 0;
+ u32 buf_size = 0;
+ bool tail = false; /* Whether linkwqe is at the end of the page */
+
+ /* When creating CQ/SCQ queue, the page size is 4k, linkwqe must be at
+ * the end of the page
+ */
+ if (object->object_type == CQM_OBJECT_NONRDMA_SCQ) {
+ /* Depth must be 2^n alignment, depth range is 256~32K */
+ if (CQM_NORDMA_CHECK_WEQ_NUMBER(wqe_number)) {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(wqe_number));
+ return CQM_FAIL;
+ }
+ if (cqm_check_align(wqe_number) == false) {
+ cqm_err(handle->dev_hdl, "Nonrdma queue alloc: wqe_number is not align on 2^n\n");
+ return CQM_FAIL;
+ }
+
+ order = CQM_4K_PAGE_ORDER; /* wqe page is 4k */
+ tail = true; /* linkwqe must be at the end of the page */
+ buf_size = CQM_4K_PAGE_SIZE;
+ } else {
+ buf_size = PAGE_SIZE << order;
+ }
+
+ /* Calculate how many buffers are required, -1 is to deduct link wqe in
+ * a buf
+ */
+ qinfo->wqe_per_buf = (buf_size / wqe_size) - 1;
+ /* The depth from service includes the number of linkwqe */
+ buf_number = ALIGN((wqe_size * wqe_number), buf_size) / buf_size;
+ /* Allocate cqm buffer */
+ q_room_buf->buf_number = buf_number;
+ q_room_buf->buf_size = buf_size;
+ q_room_buf->page_number = (buf_number << order);
+ if (cqm_buf_alloc(cqm_handle, q_room_buf, false) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_buf_alloc));
+ return CQM_FAIL;
+ }
+ /* Fill link wqe, (wqe_number - buf_number) is the number of wqe without
+ * linkwqe
+ */
+ cqm_linkwqe_fill(q_room_buf, qinfo->wqe_per_buf, wqe_size,
+ wqe_number - buf_number, tail,
+ common->queue_link_mode);
+
+ /* Create queue header */
+ qinfo->common.q_header_vaddr =
+ (struct cqm_queue_header_s *)cqm_kmalloc_align(
+ sizeof(struct cqm_queue_header_s),
+ GFP_KERNEL | __GFP_ZERO, CQM_QHEAD_ALIGN_ORDER);
+ if (!qinfo->common.q_header_vaddr) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(q_header_vaddr));
+ goto err1;
+ }
+
+ common->q_header_paddr =
+ pci_map_single(cqm_handle->dev,
+ qinfo->common.q_header_vaddr,
+ sizeof(struct cqm_queue_header_s),
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(cqm_handle->dev, common->q_header_paddr)) {
+ cqm_err(handle->dev_hdl, CQM_MAP_FAIL(q_header_vaddr));
+ goto err2;
+ }
+
+ /* Create queue ctx */
+ if (cqm_nonrdma_queue_ctx_create(object) == CQM_FAIL) {
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_nonrdma_queue_ctx_create));
+ goto err3;
+ }
+
+ return CQM_SUCCESS;
+
+err3:
+ pci_unmap_single(cqm_handle->dev, common->q_header_paddr,
+ sizeof(struct cqm_queue_header_s),
+ PCI_DMA_BIDIRECTIONAL);
+err2:
+ cqm_kfree_align(qinfo->common.q_header_vaddr);
+ qinfo->common.q_header_vaddr = NULL;
+err1:
+ cqm_buf_free(q_room_buf, cqm_handle->dev);
+ return CQM_FAIL;
+}
+
+static void cqm_nonrdma_queue_free_scq_srq(struct cqm_object_s *object,
+ struct cqm_cla_table_s *cla_table)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct cqm_queue_s *common = container_of(object,
+ struct cqm_queue_s,
+ object);
+ struct cqm_nonrdma_qinfo_s *qinfo =
+ container_of(common, struct cqm_nonrdma_qinfo_s, common);
+ struct cqm_buf_s *q_room_buf = &common->q_room_buf_1;
+ u32 index = qinfo->common.index;
+ u32 count = qinfo->index_count;
+ struct cqm_bitmap_s *bitmap = NULL;
+
+ /* If it is in TOE SRQ mode, delete the RQ */
+ if (common->queue_link_mode == CQM_QUEUE_TOE_SRQ_LINK_MODE) {
+ cqm_dbg("Nonrdma queue del: delete srq used rq\n");
+ cqm_srq_used_rq_delete(&common->object);
+ } else {
+ /* Free it if exists q room */
+ cqm_buf_free(q_room_buf, cqm_handle->dev);
+ }
+ /* Free SRQ or SCQ ctx */
+ if (object->object_type == CQM_OBJECT_NONRDMA_SRQ) {
+ /* ctx of nonrdma's SRQ is applied independently */
+ if (common->q_ctx_vaddr) {
+ pci_unmap_single(cqm_handle->dev, common->q_ctx_paddr,
+ qinfo->q_ctx_size,
+ PCI_DMA_BIDIRECTIONAL);
+
+ cqm_kfree_align(common->q_ctx_vaddr);
+ common->q_ctx_vaddr = NULL;
+ }
+ } else if (object->object_type == CQM_OBJECT_NONRDMA_SCQ) {
+ /* The ctx of SCQ of nonrdma is managed by BAT/CLA */
+ cqm_cla_put(cqm_handle, cla_table, index, count);
+
+ /* Release index into bitmap */
+ bitmap = &cla_table->bitmap;
+ cqm_bitmap_free(bitmap, index, count);
+ }
+}
+
+/**
+ * cqm_nonrdma_queue_delete - Free queue for non RDMA service
+ * @buf: cqm object
+ */
+void cqm_nonrdma_queue_delete(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = (struct cqm_handle_s *)
+ object->cqm_handle;
+ struct hifc_hwdev *handle = cqm_handle->ex_handle;
+ struct cqm_queue_s *common = container_of(object,
+ struct cqm_queue_s, object);
+ struct cqm_nonrdma_qinfo_s *qinfo = container_of(
+ common,
+ struct cqm_nonrdma_qinfo_s,
+ common);
+ struct cqm_bat_table_s *bat_table = &cqm_handle->bat_table;
+ struct cqm_cla_table_s *cla_table = NULL;
+ struct cqm_object_table_s *object_table = NULL;
+ u32 index = qinfo->common.index;
+
+ atomic_inc(&cqm_handle->ex_handle->hw_stats.cqm_stats.cqm_nonrdma_queue_delete_cnt);
+
+ /* SCQ has independent SCQN association */
+ if (object->object_type == CQM_OBJECT_NONRDMA_SCQ) {
+ cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_SCQC);
+ CQM_PTR_CHECK_NO_RET(
+ cla_table,
+ CQM_FUNCTION_FAIL(cqm_cla_table_get),
+ return);
+
+ /* index and object disassociate */
+ object_table = &cla_table->obj_table;
+
+ cqm_object_table_remove(cqm_handle, object_table,
+ index, object);
+ }
+
+ /* Wait for the completion and ensure that all references to the QPC
+ * are completed
+ */
+ if (atomic_dec_and_test(&object->refcount))
+ complete(&object->free);
+ else
+ cqm_err(handle->dev_hdl, "Nonrdma queue del: object is referred by others, has to wait for completion\n");
+ wait_for_completion(&object->free);
+
+ /* Free it if exists q header */
+ if (qinfo->common.q_header_vaddr) {
+ pci_unmap_single(cqm_handle->dev, common->q_header_paddr,
+ sizeof(struct cqm_queue_header_s),
+ PCI_DMA_BIDIRECTIONAL);
+
+ cqm_kfree_align(qinfo->common.q_header_vaddr);
+ qinfo->common.q_header_vaddr = NULL;
+ }
+ cqm_nonrdma_queue_free_scq_srq(object, cla_table);
+}
+
+#define obj_extern_if_section
+
+/**
+ * cqm_object_qpc_mpt_create - Create QPC and MPT
+ * @ex_handle: hw dev handle
+ * @service_type: service type
+ * @object_type: must be mpt and ctx
+ * @object_size: the unit is byte
+ * @object_priv: the private structure for service, can be NULL
+ * @index: get the reserved qpn based on this value, if wants to automatically
+ * allocate it, the value should be CQM_INDEX_INVALID
+ * Return: service ctx
+ */
+struct cqm_qpc_mpt_s *cqm_object_qpc_mpt_create(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 object_size, void *object_priv,
+ u32 index)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_qpc_mpt_info_s *qpc_mpt_info = NULL;
+ s32 ret = CQM_FAIL;
+
+ CQM_PTR_CHECK_RET(ex_handle, return NULL, CQM_PTR_NULL(ex_handle));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_qpc_mpt_create_cnt);
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_RET(cqm_handle, return NULL, CQM_PTR_NULL(cqm_handle));
+
+ /* If service does not register, returns NULL */
+ if (cqm_handle->service.has_register == false) {
+ cqm_err(handle->dev_hdl, "service is not register");
+ return NULL;
+ }
+
+ if (object_type != CQM_OBJECT_SERVICE_CTX) {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object_type));
+ return NULL;
+ }
+
+ qpc_mpt_info = (struct cqm_qpc_mpt_info_s *)
+ kmalloc(sizeof(struct cqm_qpc_mpt_info_s),
+ GFP_ATOMIC | __GFP_ZERO);
+ CQM_PTR_CHECK_RET(qpc_mpt_info, return NULL,
+ CQM_ALLOC_FAIL(qpc_mpt_info));
+
+ qpc_mpt_info->common.object.object_type = object_type;
+ qpc_mpt_info->common.object.object_size = object_size;
+ atomic_set(&qpc_mpt_info->common.object.refcount, 1);
+ init_completion(&qpc_mpt_info->common.object.free);
+ qpc_mpt_info->common.object.cqm_handle = cqm_handle;
+ qpc_mpt_info->common.xid = index;
+ qpc_mpt_info->common.priv = object_priv;
+
+ ret = cqm_qpc_mpt_create(&qpc_mpt_info->common.object);
+ if (ret == CQM_SUCCESS)
+ return &qpc_mpt_info->common;
+
+ cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_qpc_mpt_create));
+ kfree(qpc_mpt_info);
+ return NULL;
+}
+
+/**
+ * cqm_object_fc_srq_create - Create RQ for FC, the number of valid wqe in the
+ * queue must be meet the incoming wqe number. Because linkwqe can only be
+ * filled at the end of the page, the actual effective number exceeds demand,
+ * need to inform the number of business creation.
+ * @ex_handle: hw dev handle
+ * @service_type: service type
+ * @object_type: must be CQM_OBJECT_NONRDMA_SRQ
+ * @wqe_number: valid wqe number
+ * @wqe_size: wqe size
+ * @object_priv: the private structure for service
+ * Return: srq structure
+ */
+struct cqm_queue_s *cqm_object_fc_srq_create(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 wqe_number, u32 wqe_size,
+ void *object_priv)
+{
+ struct cqm_nonrdma_qinfo_s *nonrdma_qinfo = NULL;
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_service_s *service = NULL;
+ u32 valid_wqe_per_buffer = 0;
+ u32 wqe_sum = 0; /* includes linkwqe, normal wqe */
+ u32 buf_size = 0;
+ u32 buf_num = 0;
+ s32 ret = CQM_FAIL;
+
+ CQM_PTR_CHECK_RET(ex_handle, return NULL, CQM_PTR_NULL(ex_handle));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_fc_srq_create_cnt);
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_RET(cqm_handle, return NULL, CQM_PTR_NULL(cqm_handle));
+
+ /* service_type must be FC */
+ if (cqm_handle->service.has_register == false) {
+ cqm_err(handle->dev_hdl, "service is not register\n");
+ return NULL;
+ }
+
+ /* wqe_size can not exceed PAGE_SIZE and should not be 0, and must be
+ * 2^n aligned.
+ */
+ if ((wqe_size >= PAGE_SIZE) || (cqm_check_align(wqe_size) == false)) {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(wqe_size));
+ return NULL;
+ }
+
+ /* FC's RQ is SRQ (unlike TOE's SRQ, fc is that all packets received by
+ * the stream will be put on the same rq, and TOE's srq is similar to
+ * rq's resource pool)
+ */
+ if (object_type != CQM_OBJECT_NONRDMA_SRQ) {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object_type));
+ return NULL;
+ }
+
+ service = &cqm_handle->service;
+ buf_size = PAGE_SIZE << (service->buf_order);
+ valid_wqe_per_buffer = buf_size / wqe_size - 1; /* Minus 1 link wqe */
+ buf_num = wqe_number / valid_wqe_per_buffer;
+ if (wqe_number % valid_wqe_per_buffer != 0)
+ buf_num++;
+
+ /* Calculate the total number of all wqe */
+ wqe_sum = buf_num * (valid_wqe_per_buffer + 1);
+ nonrdma_qinfo = (struct cqm_nonrdma_qinfo_s *)
+ kmalloc(sizeof(struct cqm_nonrdma_qinfo_s),
+ GFP_KERNEL | __GFP_ZERO);
+
+ CQM_PTR_CHECK_RET(nonrdma_qinfo, return NULL,
+ CQM_ALLOC_FAIL(nonrdma_qinfo));
+
+ /* Initialize object members */
+ nonrdma_qinfo->common.object.object_type = object_type;
+ /* The total number of all wqe */
+ nonrdma_qinfo->common.object.object_size = wqe_sum;
+ atomic_set(&nonrdma_qinfo->common.object.refcount, 1);
+ init_completion(&nonrdma_qinfo->common.object.free);
+ nonrdma_qinfo->common.object.cqm_handle = cqm_handle;
+
+ /* Initialize the doorbell used by the current queue, default is the
+ * hardware doorbell
+ */
+ nonrdma_qinfo->common.current_q_doorbell = CQM_HARDWARE_DOORBELL;
+ nonrdma_qinfo->common.queue_link_mode = CQM_QUEUE_RING_MODE;
+
+ /* Initialize external public members */
+ nonrdma_qinfo->common.priv = object_priv;
+ nonrdma_qinfo->common.valid_wqe_num = wqe_sum - buf_num;
+
+ /* Initialize internal private members */
+ nonrdma_qinfo->wqe_size = wqe_size;
+ /* The SRQ for FC, which needs to create ctx */
+ nonrdma_qinfo->q_ctx_size = service->service_template.srq_ctx_size;
+
+ ret = cqm_nonrdma_queue_create(&nonrdma_qinfo->common.object);
+ if (ret == CQM_SUCCESS)
+ return &nonrdma_qinfo->common;
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_nonrdma_queue_create));
+ kfree(nonrdma_qinfo);
+ return NULL;
+}
+
+static int cqm_object_nonrdma_queue_create_check(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 wqe_size)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+
+ CQM_PTR_CHECK_RET(ex_handle, return CQM_FAIL, CQM_PTR_NULL(ex_handle));
+
+ atomic_inc(&handle->hw_stats.cqm_stats.cqm_nonrdma_queue_create_cnt);
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ CQM_PTR_CHECK_RET(cqm_handle, return CQM_FAIL,
+ CQM_PTR_NULL(cqm_handle));
+
+ /* If service does not register, returns NULL */
+ if (cqm_handle->service.has_register == false) {
+ cqm_err(handle->dev_hdl, "service is not register\n");
+ return CQM_FAIL;
+ }
+ /* Wqe size cannot exceed PAGE_SIZE, cannot be 0, and must be 2^n
+ * aligned. cqm_check_align check excludes 0, 1, non 2^n alignment
+ */
+ if ((wqe_size >= PAGE_SIZE) || (cqm_check_align(wqe_size) == false)) {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(wqe_size));
+ return CQM_FAIL;
+ }
+
+ /* Supported Nonrdma queue: RQ, SQ, SRQ, CQ, SCQ */
+ if ((object_type < CQM_OBJECT_NONRDMA_EMBEDDED_RQ) ||
+ (object_type > CQM_OBJECT_NONRDMA_SCQ)) {
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object_type));
+ return CQM_FAIL;
+ }
+
+ return CQM_SUCCESS;
+}
+
+/**
+ * cqm_object_nonrdma_queue_create - Create queues for non-RDMA services
+ * @ex_handle: hw dev handle
+ * @service_type: service type
+ * @object_type: can create embedded RQ/SQ/CQ and SRQ/SCQ
+ * @wqe_number: wqe number, including link wqe
+ * @wqe_size: wqe size, nust be 2^n
+ * @object_priv: the private structure for service, can be NULL
+ * Return: srq structure
+ */
+struct cqm_queue_s *cqm_object_nonrdma_queue_create(
+ void *ex_handle,
+ enum cqm_object_type_e object_type,
+ u32 wqe_number, u32 wqe_size,
+ void *object_priv)
+{
+ struct hifc_hwdev *handle = (struct hifc_hwdev *)ex_handle;
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct cqm_nonrdma_qinfo_s *nonrdma_qinfo = NULL;
+ struct cqm_service_s *service = NULL;
+ s32 ret = CQM_FAIL;
+
+ cqm_handle = (struct cqm_handle_s *)(handle->cqm_hdl);
+ if (cqm_object_nonrdma_queue_create_check(ex_handle,
+ object_type,
+ wqe_size) == CQM_FAIL) {
+ return NULL;
+ }
+
+ nonrdma_qinfo = (struct cqm_nonrdma_qinfo_s *)
+ kmalloc(sizeof(struct cqm_nonrdma_qinfo_s),
+ GFP_KERNEL | __GFP_ZERO);
+ CQM_PTR_CHECK_RET(nonrdma_qinfo, return NULL,
+ CQM_ALLOC_FAIL(nonrdma_qinfo));
+
+ /* Initialize object members */
+ nonrdma_qinfo->common.object.object_type = object_type;
+ nonrdma_qinfo->common.object.object_size = wqe_number;
+ atomic_set(&nonrdma_qinfo->common.object.refcount, 1);
+ init_completion(&nonrdma_qinfo->common.object.free);
+ nonrdma_qinfo->common.object.cqm_handle = cqm_handle;
+
+ /* Initialize the doorbell used by the current queue, default is the
+ * hardware doorbell
+ */
+ nonrdma_qinfo->common.current_q_doorbell = CQM_HARDWARE_DOORBELL;
+ nonrdma_qinfo->common.queue_link_mode = CQM_QUEUE_RING_MODE;
+
+ /* Initialize external public members */
+ nonrdma_qinfo->common.priv = object_priv;
+
+ /* Initialize internal private members */
+ nonrdma_qinfo->wqe_size = wqe_size;
+ service = &cqm_handle->service;
+ switch (object_type) {
+ case CQM_OBJECT_NONRDMA_SCQ:
+ nonrdma_qinfo->q_ctx_size =
+ service->service_template.scq_ctx_size;
+ break;
+ case CQM_OBJECT_NONRDMA_SRQ:
+ /* The creation for SRQ uses a dedicated interface */
+ nonrdma_qinfo->q_ctx_size =
+ service->service_template.srq_ctx_size;
+ break;
+ default:
+ break;
+ }
+
+ ret = cqm_nonrdma_queue_create(&nonrdma_qinfo->common.object);
+ if (ret == CQM_SUCCESS)
+ return &nonrdma_qinfo->common;
+
+ cqm_err(handle->dev_hdl,
+ CQM_FUNCTION_FAIL(cqm_nonrdma_queue_create));
+ kfree(nonrdma_qinfo);
+ return NULL;
+}
+
+s32 cqm_qpc_mpt_delete_ret(struct cqm_object_s *object)
+{
+ u32 object_type = 0;
+
+ object_type = object->object_type;
+ switch (object_type) {
+ case CQM_OBJECT_SERVICE_CTX:
+ cqm_qpc_mpt_delete(object);
+ return CQM_SUCCESS;
+ default:
+ return CQM_FAIL;
+ }
+}
+
+s32 cqm_nonrdma_queue_delete_ret(struct cqm_object_s *object)
+{
+ u32 object_type = 0;
+
+ object_type = object->object_type;
+ switch (object_type) {
+ case CQM_OBJECT_NONRDMA_SCQ:
+ case CQM_OBJECT_NONRDMA_SRQ:
+ cqm_nonrdma_queue_delete(object);
+ return CQM_SUCCESS;
+ default:
+ return CQM_FAIL;
+ }
+}
+
+/**
+ * cqm_object_nonrdma_queue_create - Delete the created object, the function
+ * will sleep and wait for all operations on the object to complete before
+ * returning
+ * @object: cqm object
+ */
+void cqm_object_delete(struct cqm_object_s *object)
+{
+ struct cqm_handle_s *cqm_handle = NULL;
+ struct hifc_hwdev *handle = NULL;
+
+ CQM_PTR_CHECK_NO_RET(object, CQM_PTR_NULL(object), return);
+ if (!object->cqm_handle) {
+ pr_err("[CQM]Obj del: cqm_handle is null, refcount %d\n",
+ (int)object->refcount.counter);
+ kfree(object);
+ return;
+ }
+ cqm_handle = (struct cqm_handle_s *)object->cqm_handle;
+
+ if (!cqm_handle->ex_handle) {
+ pr_err("[CQM]Obj del: ex_handle is null, refcount %d\n",
+ (int)object->refcount.counter);
+ kfree(object);
+ return;
+ }
+ handle = cqm_handle->ex_handle;
+
+ if (cqm_qpc_mpt_delete_ret(object) == CQM_SUCCESS) {
+ kfree(object);
+ return;
+ }
+
+ if (cqm_nonrdma_queue_delete_ret(object) == CQM_SUCCESS) {
+ kfree(object);
+ return;
+ }
+
+ cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->object_type));
+ kfree(object);
+}
diff --git a/drivers/scsi/huawei/hifc/hifc_cqm_object.h b/drivers/scsi/huawei/hifc/hifc_cqm_object.h
new file mode 100644
index 000000000000..308166ddd534
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_cqm_object.h
@@ -0,0 +1,244 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef __CQM_OBJECT_H__
+#define __CQM_OBJECT_H__
+
+#define CLA_TABLE_PAGE_ORDER (0)
+#define CQM_4K_PAGE_ORDER (0)
+
+#define CQM_CQ_DEPTH_MAX (32768)
+#define CQM_CQ_DEPTH_MIN (256)
+#define CQM_BAT_SIZE_FT_PF (192)
+
+#define CQM_WQE_WF_LINK 1
+#define CQM_WQE_WF_NORMAL 0
+#define CQM_QUEUE_LINK_MODE 0
+#define CQM_QUEUE_RING_MODE 1
+#define CQM_4K_PAGE_SIZE 4096
+
+#define CQM_SUCCESS 0
+#define CQM_FAIL -1
+#define CQM_QUEUE_TOE_SRQ_LINK_MODE 2
+#define CQM_CMD_TIMEOUT 10000 /*ms*/
+
+#define CQM_INDEX_INVALID ~(0U)
+#define CQM_INDEX_RESERVED (0xfffff) /* reserved by cqm alloc */
+
+enum cqm_bat_entry_type_e {
+ CQM_BAT_ENTRY_T_CFG = 0,
+ CQM_BAT_ENTRY_T_HASH,
+ CQM_BAT_ENTRY_T_QPC,
+ CQM_BAT_ENTRY_T_SCQC,
+ CQM_BAT_ENTRY_T_SRQC,
+ CQM_BAT_ENTRY_T_MPT,
+ CQM_BAT_ENTRY_T_GID,
+ CQM_BAT_ENTRY_T_LUN,
+ CQM_BAT_ENTRY_T_TASKMAP,
+ CQM_BAT_ENTRY_T_L3I,
+ CQM_BAT_ENTRY_T_CHILDC,
+ CQM_BAT_ENTRY_T_TIMER,
+ CQM_BAT_ENTRY_T_XID2CID,
+ CQM_BAT_ENTRY_T_REORDER,
+
+ CQM_BAT_ENTRY_T_INVALID = 0xff,
+};
+
+enum cqm_cmd_type_e {
+ CQM_CMD_T_INVALID = 0,
+ CQM_CMD_T_BAT_UPDATE,
+ CQM_CMD_T_CLA_UPDATE,
+ CQM_CMD_T_BLOOMFILTER_SET,
+ CQM_CMD_T_BLOOMFILTER_CLEAR,
+ CQM_CMD_T_COMPACT_SRQ_UPDATE,
+ CQM_CMD_T_CLA_CACHE_INVALID,
+ CQM_CMD_T_BLOOMFILTER_INIT,
+ QM_CMD_T_MAX
+};
+
+/*linkwqe*/
+#define CQM_LINK_WQE_CTRLSL_VALUE 2
+#define CQM_LINK_WQE_LP_VALID 1
+#define CQM_LINK_WQE_LP_INVALID 0
+#define CQM_LINK_WQE_OWNER_VALID 1
+#define CQM_LINK_WQE_OWNER_INVALID 0
+
+/*CLA update mode*/
+#define CQM_CLA_RECORD_NEW_GPA 0
+#define CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID 1
+#define CQM_CLA_DEL_GPA_WITH_CACHE_INVALID 2
+
+#define CQM_CLA_LVL_0 0
+#define CQM_CLA_LVL_1 1
+#define CQM_CLA_LVL_2 2
+
+#define CQM_MAX_INDEX_BIT 19
+#define CQM_CHIP_CACHELINE 256
+enum cqm_cmd_ack_type_e {
+ CQM_CMD_ACK_TYPE_CMDQ = 0, /* ack: write back to cmdq */
+ CQM_CMD_ACK_TYPE_SHARE_CQN = 1, /* ack report scq by root ctx ctx */
+ CQM_CMD_ACK_TYPE_APP_CQN = 2 /* ack report scq by parent ctx */
+};
+
+struct cqm_bat_entry_cfg_s {
+ u32 cur_conn_num_h_4 :4;
+ u32 rsv1 :4;
+ u32 max_conn_num :20;
+ u32 rsv2 :4;
+
+ u32 max_conn_cache :10;
+ u32 rsv3 :6;
+ u32 cur_conn_num_l_16 :16;
+
+ u32 bloom_filter_addr :16;
+ u32 cur_conn_cache :10;
+ u32 rsv4 :6;
+
+ u32 bucket_num :16;
+ u32 bloom_filter_len :16;
+};
+
+#define CQM_BAT_NO_BYPASS_CACHE 0
+#define CQM_BAT_ENTRY_SIZE_256 0
+#define CQM_BAT_ENTRY_SIZE_512 1
+#define CQM_BAT_ENTRY_SIZE_1024 2
+
+struct cqm_bat_entry_standerd_s {
+ u32 entry_size :2;
+ u32 rsv1 :6;
+ u32 max_number :20;
+ u32 rsv2 :4;
+
+ u32 cla_gpa_h :32;
+
+ u32 cla_gpa_l :32;
+
+ u32 rsv3 :8;
+ u32 z :5;
+ u32 y :5;
+ u32 x :5;
+ u32 rsv24 :1;
+ u32 bypass :1;
+ u32 cla_level :2;
+ u32 rsv5 :5;
+};
+
+struct cqm_bat_entry_taskmap_s {
+ u32 gpa0_h;
+ u32 gpa0_l;
+
+ u32 gpa1_h;
+ u32 gpa1_l;
+
+ u32 gpa2_h;
+ u32 gpa2_l;
+
+ u32 gpa3_h;
+ u32 gpa3_l;
+};
+
+struct cqm_cla_cache_invalid_cmd_s {
+ u32 gpa_h;
+ u32 gpa_l;
+ u32 cache_size;/* CLA cache size=4096B */
+};
+
+struct cqm_cla_update_cmd_s {
+ /* need to update gpa addr */
+ u32 gpa_h;
+ u32 gpa_l;
+
+ /* update value */
+ u32 value_h;
+ u32 value_l;
+};
+
+struct cqm_bat_update_cmd_s {
+#define CQM_BAT_MAX_SIZE 256
+ u32 offset; /* byte offset,16Byte aligned */
+ u32 byte_len; /* max size: 256byte */
+ u8 data[CQM_BAT_MAX_SIZE];
+};
+
+struct cqm_handle_s;
+
+struct cqm_linkwqe_s {
+ u32 rsv1 :14;
+ u32 wf :1;
+ u32 rsv2 :14;
+ u32 ctrlsl :2;
+ u32 o :1;
+
+ u32 rsv3 :31;
+ u32 lp :1;
+
+ u32 next_page_gpa_h;
+ u32 next_page_gpa_l;
+
+ u32 next_buffer_addr_h;
+ u32 next_buffer_addr_l;
+};
+
+struct cqm_srq_linkwqe_s {
+ struct cqm_linkwqe_s linkwqe;
+ /*add by wss for srq*/
+ u32 current_buffer_gpa_h;
+ u32 current_buffer_gpa_l;
+ u32 current_buffer_addr_h;
+ u32 current_buffer_addr_l;
+
+ u32 fast_link_page_addr_h;
+ u32 fast_link_page_addr_l;
+
+ u32 fixed_next_buffer_addr_h;
+ u32 fixed_next_buffer_addr_l;
+};
+
+union cqm_linkwqe_first_64b_s {
+ struct cqm_linkwqe_s basic_linkwqe;
+ u32 value[16];
+};
+
+struct cqm_linkwqe_second_64b_s {
+ u32 rsvd0[4];
+ u32 rsvd1[4];
+ union {
+ struct {
+ u32 rsvd0[3];
+ u32 rsvd1 :29;
+ u32 toe_o :1;
+ u32 resvd2 :2;
+ } bs;
+ u32 value[4];
+ } third_16B;
+
+ union {
+ struct {
+ u32 rsvd0[2];
+ u32 rsvd1 :31;
+ u32 ifoe_o :1;
+ u32 rsvd2;
+ } bs;
+ u32 value[4];
+ } forth_16B;
+
+};
+
+struct cqm_linkwqe_128b_s {
+ union cqm_linkwqe_first_64b_s first_64b;
+ struct cqm_linkwqe_second_64b_s second_64b;
+};
+
+s32 cqm_bat_init(struct cqm_handle_s *cqm_handle);
+void cqm_bat_uninit(struct cqm_handle_s *cqm_handle);
+s32 cqm_cla_init(struct cqm_handle_s *cqm_handle);
+void cqm_cla_uninit(struct cqm_handle_s *cqm_handle);
+s32 cqm_bitmap_init(struct cqm_handle_s *cqm_handle);
+void cqm_bitmap_uninit(struct cqm_handle_s *cqm_handle);
+s32 cqm_object_table_init(struct cqm_handle_s *cqm_handle);
+void cqm_object_table_uninit(struct cqm_handle_s *cqm_handle);
+
+#endif /* __CQM_OBJECT_H__ */
diff --git a/drivers/scsi/huawei/hifc/hifc_eqs.c b/drivers/scsi/huawei/hifc/hifc_eqs.c
new file mode 100644
index 000000000000..803866e1fbf9
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_eqs.c
@@ -0,0 +1,1347 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_hwdev.h"
+#include "hifc_eqs.h"
+
+#define HIFC_EQS_WQ_NAME "hifc_eqs"
+
+#define AEQ_CTRL_0_INTR_IDX_SHIFT 0
+#define AEQ_CTRL_0_FUNC_BUSY_SHIFT 10
+#define AEQ_CTRL_0_DMA_ATTR_SHIFT 12
+#define AEQ_CTRL_0_PCI_INTF_IDX_SHIFT 20
+#define AEQ_CTRL_0_QPS_NUM_SHIFT 22
+#define AEQ_CTRL_0_INTR_MODE_SHIFT 31
+
+#define AEQ_CTRL_0_INTR_IDX_MASK 0x3FFU
+#define AEQ_CTRL_0_FUNC_BUSY_MASK 0x1U
+#define AEQ_CTRL_0_DMA_ATTR_MASK 0x3FU
+#define AEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3U
+#define AEQ_CTRL_0_QPS_NUM_MASK 0xFFU
+#define AEQ_CTRL_0_INTR_MODE_MASK 0x1U
+
+#define AEQ_CTRL_0_GET(val, member) \
+ (((val) >> AEQ_CTRL_0_##member##_SHIFT) & \
+ AEQ_CTRL_0_##member##_MASK)
+
+#define AEQ_CTRL_0_SET(val, member) \
+ (((val) & AEQ_CTRL_0_##member##_MASK) << \
+ AEQ_CTRL_0_##member##_SHIFT)
+
+#define AEQ_CTRL_0_CLEAR(val, member) \
+ ((val) & (~(AEQ_CTRL_0_##member##_MASK \
+ << AEQ_CTRL_0_##member##_SHIFT)))
+
+#define AEQ_CTRL_1_LEN_SHIFT 0
+#define AEQ_CTRL_1_FUNC_OWN_SHIFT 21
+#define AEQ_CTRL_1_ELEM_SIZE_SHIFT 24
+#define AEQ_CTRL_1_PAGE_SIZE_SHIFT 28
+
+#define AEQ_CTRL_1_LEN_MASK 0x1FFFFFU
+#define AEQ_CTRL_1_FUNC_OWN_MASK 0x1U
+#define AEQ_CTRL_1_ELEM_SIZE_MASK 0x3U
+#define AEQ_CTRL_1_PAGE_SIZE_MASK 0xFU
+
+#define AEQ_CTRL_1_GET(val, member) \
+ (((val) >> AEQ_CTRL_1_##member##_SHIFT) & \
+ AEQ_CTRL_1_##member##_MASK)
+
+#define AEQ_CTRL_1_SET(val, member) \
+ (((val) & AEQ_CTRL_1_##member##_MASK) << \
+ AEQ_CTRL_1_##member##_SHIFT)
+
+#define AEQ_CTRL_1_CLEAR(val, member) \
+ ((val) & (~(AEQ_CTRL_1_##member##_MASK \
+ << AEQ_CTRL_1_##member##_SHIFT)))
+
+#define HIFC_EQ_PROD_IDX_MASK 0xFFFFF
+#define HIFC_TASK_PROCESS_EQE_LIMIT 1024
+#define HIFC_EQ_UPDATE_CI_STEP 64
+
+static uint g_aeq_len = HIFC_DEFAULT_AEQ_LEN;
+module_param(g_aeq_len, uint, 0444);
+MODULE_PARM_DESC(g_aeq_len,
+ "aeq depth, valid range is " __stringify(HIFC_MIN_AEQ_LEN)
+ " - " __stringify(HIFC_MAX_AEQ_LEN));
+
+static uint g_ceq_len = HIFC_DEFAULT_CEQ_LEN;
+module_param(g_ceq_len, uint, 0444);
+MODULE_PARM_DESC(g_ceq_len,
+ "ceq depth, valid range is " __stringify(HIFC_MIN_CEQ_LEN)
+ " - " __stringify(HIFC_MAX_CEQ_LEN));
+
+static uint g_num_ceqe_in_tasklet = HIFC_TASK_PROCESS_EQE_LIMIT;
+module_param(g_num_ceqe_in_tasklet, uint, 0444);
+MODULE_PARM_DESC(g_num_ceqe_in_tasklet,
+ "The max number of ceqe can be processed in tasklet, default = 1024");
+
+#define CEQ_CTRL_0_INTR_IDX_SHIFT 0
+#define CEQ_CTRL_0_DMA_ATTR_SHIFT 12
+#define CEQ_CTRL_0_LIMIT_KICK_SHIFT 20
+#define CEQ_CTRL_0_PCI_INTF_IDX_SHIFT 24
+#define CEQ_CTRL_0_INTR_MODE_SHIFT 31
+
+#define CEQ_CTRL_0_INTR_IDX_MASK 0x3FFU
+#define CEQ_CTRL_0_DMA_ATTR_MASK 0x3FU
+#define CEQ_CTRL_0_LIMIT_KICK_MASK 0xFU
+#define CEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3U
+#define CEQ_CTRL_0_INTR_MODE_MASK 0x1U
+
+#define CEQ_CTRL_0_SET(val, member) \
+ (((val) & CEQ_CTRL_0_##member##_MASK) << \
+ CEQ_CTRL_0_##member##_SHIFT)
+
+#define CEQ_CTRL_1_LEN_SHIFT 0
+#define CEQ_CTRL_1_PAGE_SIZE_SHIFT 28
+#define CEQ_CTRL_1_LEN_MASK 0x1FFFFFU
+#define CEQ_CTRL_1_PAGE_SIZE_MASK 0xFU
+
+#define CEQ_CTRL_1_SET(val, member) \
+ (((val) & CEQ_CTRL_1_##member##_MASK) << \
+ CEQ_CTRL_1_##member##_SHIFT)
+
+#define EQ_ELEM_DESC_TYPE_SHIFT 0
+#define EQ_ELEM_DESC_SRC_SHIFT 7
+#define EQ_ELEM_DESC_SIZE_SHIFT 8
+#define EQ_ELEM_DESC_WRAPPED_SHIFT 31
+#define EQ_ELEM_DESC_TYPE_MASK 0x7FU
+#define EQ_ELEM_DESC_SRC_MASK 0x1U
+#define EQ_ELEM_DESC_SIZE_MASK 0xFFU
+#define EQ_ELEM_DESC_WRAPPED_MASK 0x1U
+
+#define EQ_ELEM_DESC_GET(val, member) \
+ (((val) >> EQ_ELEM_DESC_##member##_SHIFT) & \
+ EQ_ELEM_DESC_##member##_MASK)
+
+#define EQ_CONS_IDX_CONS_IDX_SHIFT 0
+#define EQ_CONS_IDX_XOR_CHKSUM_SHIFT 24
+#define EQ_CONS_IDX_INT_ARMED_SHIFT 31
+#define EQ_CONS_IDX_CONS_IDX_MASK 0x1FFFFFU
+#define EQ_CONS_IDX_XOR_CHKSUM_MASK 0xFU
+#define EQ_CONS_IDX_INT_ARMED_MASK 0x1U
+
+#define EQ_CONS_IDX_SET(val, member) \
+ (((val) & EQ_CONS_IDX_##member##_MASK) << \
+ EQ_CONS_IDX_##member##_SHIFT)
+
+#define EQ_CONS_IDX_CLEAR(val, member) \
+ ((val) & (~(EQ_CONS_IDX_##member##_MASK \
+ << EQ_CONS_IDX_##member##_SHIFT)))
+
+#define EQ_WRAPPED(eq) ((u32)(eq)->wrapped << EQ_VALID_SHIFT)
+
+#define EQ_CONS_IDX(eq) ((eq)->cons_idx | \
+ ((u32)(eq)->wrapped << EQ_WRAPPED_SHIFT))
+
+#define EQ_CONS_IDX_REG_ADDR(eq) (((eq)->type == HIFC_AEQ) ? \
+ HIFC_CSR_AEQ_CONS_IDX_ADDR((eq)->q_id) : \
+ HIFC_CSR_CEQ_CONS_IDX_ADDR((eq)->q_id))
+
+#define EQ_PROD_IDX_REG_ADDR(eq) (((eq)->type == HIFC_AEQ) ? \
+ HIFC_CSR_AEQ_PROD_IDX_ADDR((eq)->q_id) : \
+ HIFC_CSR_CEQ_PROD_IDX_ADDR((eq)->q_id))
+
+#define GET_EQ_NUM_PAGES(eq, size) \
+ ((u16)(ALIGN((u32)((eq)->eq_len * (eq)->elem_size), \
+ (size)) / (size)))
+
+#define GET_EQ_NUM_ELEMS(eq, pg_size) ((pg_size) / (u32)(eq)->elem_size)
+
+#define GET_EQ_ELEMENT(eq, idx) \
+ (((u8 *)(eq)->virt_addr[(idx) / (eq)->num_elem_in_pg]) + \
+ (u32)(((idx) & ((eq)->num_elem_in_pg - 1)) * (eq)->elem_size))
+
+#define GET_AEQ_ELEM(eq, idx) ((struct hifc_aeq_elem *)\
+ GET_EQ_ELEMENT((eq), (idx)))
+
+#define GET_CEQ_ELEM(eq, idx) ((u32 *)GET_EQ_ELEMENT((eq), (idx)))
+
+#define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM((eq), (eq)->cons_idx)
+
+#define GET_CURR_CEQ_ELEM(eq) GET_CEQ_ELEM((eq), (eq)->cons_idx)
+
+#define PAGE_IN_4K(page_size) ((page_size) >> 12)
+#define EQ_SET_HW_PAGE_SIZE_VAL(eq) \
+ ((u32)ilog2(PAGE_IN_4K((eq)->page_size)))
+
+#define ELEMENT_SIZE_IN_32B(eq) (((eq)->elem_size) >> 5)
+#define EQ_SET_HW_ELEM_SIZE_VAL(eq) ((u32)ilog2(ELEMENT_SIZE_IN_32B(eq)))
+
+#define AEQ_DMA_ATTR_DEFAULT 0
+#define CEQ_DMA_ATTR_DEFAULT 0
+#define CEQ_LMT_KICK_DEFAULT 0
+#define EQ_MSIX_RESEND_TIMER_CLEAR 1
+#define EQ_WRAPPED_SHIFT 20
+#define EQ_VALID_SHIFT 31
+#define CEQE_TYPE_SHIFT 23
+#define CEQE_TYPE_MASK 0x7
+
+#define CEQE_TYPE(type) (((type) >> CEQE_TYPE_SHIFT) & \
+ CEQE_TYPE_MASK)
+#define CEQE_DATA_MASK 0x3FFFFFF
+#define CEQE_DATA(data) ((data) & CEQE_DATA_MASK)
+#define EQ_MIN_PAGE_SIZE 0x1000U
+#define aeq_to_aeqs(eq) \
+ container_of((eq) - (eq)->q_id, struct hifc_aeqs, aeq[0])
+
+#define ceq_to_ceqs(eq) \
+ container_of((eq) - (eq)->q_id, struct hifc_ceqs, ceq[0])
+
+/**
+ * aeq_interrupt - aeq interrupt handler
+ * @irq: irq number
+ * @data: the async event queue of the event
+ **/
+static irqreturn_t aeq_interrupt(int irq, void *data)
+{
+ struct hifc_eq *aeq = (struct hifc_eq *)data;
+ struct hifc_hwdev *hwdev = aeq->hwdev;
+
+ struct hifc_aeqs *aeqs = aeq_to_aeqs(aeq);
+ struct workqueue_struct *workq = aeqs->workq;
+ struct hifc_eq_work *aeq_work;
+
+ /* clear resend timer cnt register */
+ hifc_misx_intr_clear_resend_bit(hwdev, aeq->eq_irq.msix_entry_idx,
+ EQ_MSIX_RESEND_TIMER_CLEAR);
+
+ aeq_work = &aeq->aeq_work;
+ aeq_work->data = aeq;
+
+ queue_work(workq, &aeq_work->work);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ceq_interrupt - ceq interrupt handler
+ * @irq: irq number
+ * @data: the completion event queue of the event
+ **/
+static irqreturn_t ceq_interrupt(int irq, void *data)
+{
+ struct hifc_eq *ceq = (struct hifc_eq *)data;
+ struct hifc_ceq_tasklet_data *ceq_tasklet_data;
+
+ ceq->hard_intr_jif = jiffies;
+
+ /* clear resend timer counters */
+ hifc_misx_intr_clear_resend_bit(ceq->hwdev, ceq->eq_irq.msix_entry_idx,
+ EQ_MSIX_RESEND_TIMER_CLEAR);
+
+ ceq_tasklet_data = &ceq->ceq_tasklet_data;
+ ceq_tasklet_data->data = data;
+ tasklet_schedule(&ceq->ceq_tasklet);
+
+ return IRQ_HANDLED;
+}
+
+static u8 eq_cons_idx_checksum_set(u32 val)
+{
+ u8 checksum = 0;
+ u8 idx;
+
+ for (idx = 0; idx < 32; idx += 4)
+ checksum ^= ((val >> idx) & 0xF);
+
+ return checksum & 0xF;
+}
+
+/**
+ * hifc_aeq_register_hw_cb - register aeq callback for specific event
+ * @hwdev: pointer to hw device
+ * @event: event for the handler
+ * @hw_cb: callback function
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_aeq_register_hw_cb(void *hwdev, enum hifc_aeq_type event,
+ hifc_aeq_hwe_cb hwe_cb)
+{
+ struct hifc_aeqs *aeqs;
+
+ if (!hwdev || !hwe_cb || event >= HIFC_MAX_AEQ_EVENTS)
+ return -EINVAL;
+
+ aeqs = ((struct hifc_hwdev *)hwdev)->aeqs;
+
+ aeqs->aeq_hwe_cb[event] = hwe_cb;
+
+ set_bit(HIFC_AEQ_HW_CB_REG, &aeqs->aeq_hw_cb_state[event]);
+
+ return 0;
+}
+
+/**
+ * hifc_aeq_unregister_hw_cb - unregister the aeq callback for specific event
+ * @hwdev: pointer to hw device
+ * @event: event for the handler
+ **/
+void hifc_aeq_unregister_hw_cb(void *hwdev, enum hifc_aeq_type event)
+{
+ struct hifc_aeqs *aeqs;
+
+ if (!hwdev || event >= HIFC_MAX_AEQ_EVENTS)
+ return;
+
+ aeqs = ((struct hifc_hwdev *)hwdev)->aeqs;
+
+ clear_bit(HIFC_AEQ_HW_CB_REG, &aeqs->aeq_hw_cb_state[event]);
+
+ while (test_bit(HIFC_AEQ_HW_CB_RUNNING, &aeqs->aeq_hw_cb_state[event]))
+ usleep_range(900, 1000);
+
+ aeqs->aeq_hwe_cb[event] = NULL;
+}
+
+/**
+ * hifc_aeq_register_sw_cb - register aeq callback for sw event
+ * @hwdev: pointer to hw device
+ * @event: soft event for the handler
+ * @sw_cb: callback function
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_aeq_register_swe_cb(void *hwdev, enum hifc_aeq_sw_type event,
+ hifc_aeq_swe_cb aeq_swe_cb)
+{
+ struct hifc_aeqs *aeqs;
+
+ if (!hwdev || !aeq_swe_cb || event >= HIFC_MAX_AEQ_SW_EVENTS)
+ return -EINVAL;
+
+ aeqs = ((struct hifc_hwdev *)hwdev)->aeqs;
+
+ aeqs->aeq_swe_cb[event] = aeq_swe_cb;
+
+ set_bit(HIFC_AEQ_SW_CB_REG, &aeqs->aeq_sw_cb_state[event]);
+
+ return 0;
+}
+
+/**
+ * hifc_aeq_unregister_sw_cb - unregister the aeq callback for sw event
+ * @hwdev: pointer to hw device
+ * @event: soft event for the handler
+ **/
+void hifc_aeq_unregister_swe_cb(void *hwdev, enum hifc_aeq_sw_type event)
+{
+ struct hifc_aeqs *aeqs;
+
+ if (!hwdev || event >= HIFC_MAX_AEQ_SW_EVENTS)
+ return;
+
+ aeqs = ((struct hifc_hwdev *)hwdev)->aeqs;
+
+ clear_bit(HIFC_AEQ_SW_CB_REG, &aeqs->aeq_sw_cb_state[event]);
+
+ while (test_bit(HIFC_AEQ_SW_CB_RUNNING, &aeqs->aeq_sw_cb_state[event]))
+ usleep_range(900, 1000);
+
+ aeqs->aeq_swe_cb[event] = NULL;
+}
+
+/**
+ * hifc_ceq_register_sw_cb - register ceq callback for specific event
+ * @hwdev: pointer to hw device
+ * @event: event for the handler
+ * @callback: callback function
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_ceq_register_cb(void *hwdev, enum hifc_ceq_event event,
+ hifc_ceq_event_cb callback)
+{
+ struct hifc_ceqs *ceqs;
+
+ if (!hwdev || event >= HIFC_MAX_CEQ_EVENTS)
+ return -EINVAL;
+
+ ceqs = ((struct hifc_hwdev *)hwdev)->ceqs;
+
+ ceqs->ceq_cb[event] = callback;
+
+ set_bit(HIFC_CEQ_CB_REG, &ceqs->ceq_cb_state[event]);
+
+ return 0;
+}
+
+/**
+ * hifc_ceq_unregister_cb - unregister ceq callback for specific event
+ * @hwdev: pointer to hw device
+ * @event: event for the handler
+ **/
+void hifc_ceq_unregister_cb(void *hwdev, enum hifc_ceq_event event)
+{
+ struct hifc_ceqs *ceqs;
+
+ if (!hwdev || event >= HIFC_MAX_CEQ_EVENTS)
+ return;
+
+ ceqs = ((struct hifc_hwdev *)hwdev)->ceqs;
+
+ clear_bit(HIFC_CEQ_CB_REG, &ceqs->ceq_cb_state[event]);
+
+ while (test_bit(HIFC_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]))
+ usleep_range(900, 1000);
+
+ ceqs->ceq_cb[event] = NULL;
+}
+
+/**
+ * set_eq_cons_idx - write the cons idx to the hw
+ * @eq: The event queue to update the cons idx for
+ * @arm_state: arm state value
+ **/
+static void set_eq_cons_idx(struct hifc_eq *eq, u32 arm_state)
+{
+ u32 eq_wrap_ci, val;
+ u32 addr = EQ_CONS_IDX_REG_ADDR(eq);
+
+ eq_wrap_ci = EQ_CONS_IDX(eq);
+
+ /* other filed is resverd, set to 0 */
+ val = EQ_CONS_IDX_SET(eq_wrap_ci, CONS_IDX) |
+ EQ_CONS_IDX_SET(arm_state, INT_ARMED);
+
+ val |= EQ_CONS_IDX_SET(eq_cons_idx_checksum_set(val), XOR_CHKSUM);
+
+ hifc_hwif_write_reg(eq->hwdev->hwif, addr, val);
+}
+
+/**
+ * ceq_event_handler - handle for the ceq events
+ * @eqs: eqs part of the chip
+ * @ceqe: ceq element of the event
+ **/
+static void ceq_event_handler(struct hifc_ceqs *ceqs, u32 ceqe)
+{
+ struct hifc_hwdev *hwdev = ceqs->hwdev;
+ enum hifc_ceq_event event = CEQE_TYPE(ceqe);
+ u32 ceqe_data = CEQE_DATA(ceqe);
+
+ if (event >= HIFC_MAX_CEQ_EVENTS) {
+ sdk_err(hwdev->dev_hdl, "Ceq unknown event:%d, ceqe date: 0x%x\n",
+ event, ceqe_data);
+ return;
+ }
+
+ set_bit(HIFC_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]);
+
+ if (ceqs->ceq_cb[event] &&
+ test_bit(HIFC_CEQ_CB_REG, &ceqs->ceq_cb_state[event]))
+ ceqs->ceq_cb[event](hwdev, ceqe_data);
+
+ clear_bit(HIFC_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]);
+}
+
+static void aeq_swe_handler(struct hifc_aeqs *aeqs,
+ struct hifc_aeq_elem *aeqe_pos,
+ enum hifc_aeq_type event)
+{
+ enum hifc_ucode_event_type ucode_event;
+ enum hifc_aeq_sw_type sw_event;
+ u64 aeqe_data;
+ u8 lev;
+
+ ucode_event = event;
+ /* SW event uses only the first 8B */
+ sw_event = ucode_event >= HIFC_NIC_FATAL_ERROR_MAX ?
+ HIFC_STATEFULL_EVENT :
+ HIFC_STATELESS_EVENT;
+ aeqe_data = be64_to_cpu((*(u64 *)aeqe_pos->aeqe_data));
+ set_bit(HIFC_AEQ_SW_CB_RUNNING,
+ &aeqs->aeq_sw_cb_state[sw_event]);
+ if (aeqs->aeq_swe_cb[sw_event] &&
+ test_bit(HIFC_AEQ_SW_CB_REG,
+ &aeqs->aeq_sw_cb_state[sw_event])) {
+ lev = aeqs->aeq_swe_cb[sw_event](aeqs->hwdev,
+ ucode_event,
+ aeqe_data);
+ hifc_swe_fault_handler(aeqs->hwdev, lev,
+ ucode_event, aeqe_data);
+ }
+ clear_bit(HIFC_AEQ_SW_CB_RUNNING,
+ &aeqs->aeq_sw_cb_state[sw_event]);
+}
+
+static void aeq_hwe_handler(struct hifc_aeqs *aeqs,
+ struct hifc_aeq_elem *aeqe_pos,
+ enum hifc_aeq_type event, u32 aeqe_desc)
+{
+ u8 size;
+
+ if (event < HIFC_MAX_AEQ_EVENTS) {
+ size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE);
+ set_bit(HIFC_AEQ_HW_CB_RUNNING,
+ &aeqs->aeq_hw_cb_state[event]);
+ if (aeqs->aeq_hwe_cb[event] &&
+ test_bit(HIFC_AEQ_HW_CB_REG,
+ &aeqs->aeq_hw_cb_state[event]))
+ aeqs->aeq_hwe_cb[event](aeqs->hwdev,
+ aeqe_pos->aeqe_data, size);
+ clear_bit(HIFC_AEQ_HW_CB_RUNNING,
+ &aeqs->aeq_hw_cb_state[event]);
+
+ return;
+ }
+
+ sdk_warn(aeqs->hwdev->dev_hdl, "Unknown aeq hw event %d\n", event);
+}
+
+/**
+ * aeq_irq_handler - handler for the aeq event
+ * @eq: the async event queue of the event
+ * Return: true - success, false - failure
+ **/
+static bool aeq_irq_handler(struct hifc_eq *eq)
+{
+ struct hifc_aeqs *aeqs = aeq_to_aeqs(eq);
+ struct hifc_aeq_elem *aeqe_pos;
+ enum hifc_aeq_type event;
+ u32 aeqe_desc;
+ u32 i, eqe_cnt = 0;
+
+ for (i = 0; i < HIFC_TASK_PROCESS_EQE_LIMIT; i++) {
+ aeqe_pos = GET_CURR_AEQ_ELEM(eq);
+
+ /* Data in HW is in Big endian Format */
+ aeqe_desc = be32_to_cpu(aeqe_pos->desc);
+
+ /* HW updates wrapped bit, when it adds eq element event */
+ if (EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) == eq->wrapped)
+ return false;
+
+ /* This memory barrier is needed to keep us from reading
+ * any other fields out of the cmdq wqe until we have
+ * verified the command has been processed and
+ * written back.
+ */
+ dma_rmb();
+
+ event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
+ if (EQ_ELEM_DESC_GET(aeqe_desc, SRC))
+ aeq_swe_handler(aeqs, aeqe_pos, event);
+ else
+ aeq_hwe_handler(aeqs, aeqe_pos, event, aeqe_desc);
+
+ eq->cons_idx++;
+
+ if (eq->cons_idx == eq->eq_len) {
+ eq->cons_idx = 0;
+ eq->wrapped = !eq->wrapped;
+ }
+
+ if (++eqe_cnt >= HIFC_EQ_UPDATE_CI_STEP) {
+ eqe_cnt = 0;
+ set_eq_cons_idx(eq, HIFC_EQ_NOT_ARMED);
+ }
+ }
+
+ return true;
+}
+
+/**
+ * ceq_irq_handler - handler for the ceq event
+ * @eq: the completion event queue of the event
+ * Return: true - success, false - failure
+ **/
+static bool ceq_irq_handler(struct hifc_eq *eq)
+{
+ struct hifc_ceqs *ceqs = ceq_to_ceqs(eq);
+ u32 ceqe, eqe_cnt = 0;
+ u32 i;
+
+ for (i = 0; i < g_num_ceqe_in_tasklet; i++) {
+ ceqe = *(GET_CURR_CEQ_ELEM(eq));
+ ceqe = be32_to_cpu(ceqe);
+
+ /* HW updates wrapped bit, when it adds eq element event */
+ if (EQ_ELEM_DESC_GET(ceqe, WRAPPED) == eq->wrapped)
+ return false;
+
+ ceq_event_handler(ceqs, ceqe);
+
+ eq->cons_idx++;
+
+ if (eq->cons_idx == eq->eq_len) {
+ eq->cons_idx = 0;
+ eq->wrapped = !eq->wrapped;
+ }
+
+ if (++eqe_cnt >= HIFC_EQ_UPDATE_CI_STEP) {
+ eqe_cnt = 0;
+ set_eq_cons_idx(eq, HIFC_EQ_NOT_ARMED);
+ }
+ }
+
+ return true;
+}
+
+/**
+ * eq_irq_handler - handler for the eq event
+ * @data: the event queue of the event
+ * Return: true - success, false - failure
+ **/
+static bool eq_irq_handler(void *data)
+{
+ struct hifc_eq *eq = (struct hifc_eq *)data;
+ bool uncompleted;
+
+ if (eq->type == HIFC_AEQ)
+ uncompleted = aeq_irq_handler(eq);
+ else
+ uncompleted = ceq_irq_handler(eq);
+
+ set_eq_cons_idx(eq, uncompleted ? HIFC_EQ_NOT_ARMED : HIFC_EQ_ARMED);
+
+ return uncompleted;
+}
+
+static void reschedule_eq_handler(struct hifc_eq *eq)
+{
+ if (eq->type == HIFC_AEQ) {
+ struct hifc_aeqs *aeqs = aeq_to_aeqs(eq);
+ struct workqueue_struct *workq = aeqs->workq;
+ struct hifc_eq_work *aeq_work = &eq->aeq_work;
+
+ queue_work(workq, &aeq_work->work);
+ } else {
+ tasklet_schedule(&eq->ceq_tasklet);
+ }
+}
+
+/**
+ * ceq_tasklet - ceq tasklet for the event
+ * @ceq_data: data that will be used by the tasklet(ceq)
+ **/
+
+static void ceq_tasklet(ulong ceq_data)
+{
+ struct hifc_ceq_tasklet_data *ceq_tasklet_data =
+ (struct hifc_ceq_tasklet_data *)ceq_data;
+ struct hifc_eq *eq = (struct hifc_eq *)ceq_tasklet_data->data;
+
+ eq->soft_intr_jif = jiffies;
+
+ if (eq_irq_handler(ceq_tasklet_data->data))
+ reschedule_eq_handler(ceq_tasklet_data->data);
+}
+
+/**
+ * eq_irq_work - eq work for the event
+ * @work: the work that is associated with the eq
+ **/
+static void eq_irq_work(struct work_struct *work)
+{
+ struct hifc_eq_work *aeq_work =
+ container_of(work, struct hifc_eq_work, work);
+
+ if (eq_irq_handler(aeq_work->data))
+ reschedule_eq_handler(aeq_work->data);
+}
+
+struct hifc_ceq_ctrl_reg {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 q_id;
+ u32 ctrl0;
+ u32 ctrl1;
+};
+
+static int set_ceq_ctrl_reg(struct hifc_hwdev *hwdev, u16 q_id,
+ u32 ctrl0, u32 ctrl1)
+{
+ struct hifc_ceq_ctrl_reg ceq_ctrl = {0};
+ u16 in_size = sizeof(ceq_ctrl);
+ u16 out_size = sizeof(ceq_ctrl);
+ int err;
+
+ err = hifc_global_func_id_get(hwdev, &ceq_ctrl.func_id);
+ if (err)
+ return err;
+
+ ceq_ctrl.q_id = q_id;
+ ceq_ctrl.ctrl0 = ctrl0;
+ ceq_ctrl.ctrl1 = ctrl1;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_CEQ_CTRL_REG_WR_BY_UP,
+ &ceq_ctrl, in_size,
+ &ceq_ctrl, &out_size, 0);
+ if (err || !out_size || ceq_ctrl.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to set ceq %d ctrl reg, err: %d status: 0x%x, out_size: 0x%x\n",
+ q_id, err, ceq_ctrl.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/**
+ * set_eq_ctrls - setting eq's ctrls registers
+ * @eq: the event queue for setting
+ * Return: 0 - success, negative - failure
+ **/
+static int set_eq_ctrls(struct hifc_eq *eq)
+{
+ enum hifc_eq_type type = eq->type;
+ struct hifc_hwif *hwif = eq->hwdev->hwif;
+ struct irq_info *eq_irq = &eq->eq_irq;
+ u32 addr, val, ctrl0, ctrl1, page_size_val, elem_size;
+ u32 pci_intf_idx = HIFC_PCI_INTF_IDX(hwif);
+ int err;
+
+ if (type == HIFC_AEQ) {
+ /* set ctrl0 */
+ addr = HIFC_CSR_AEQ_CTRL_0_ADDR(eq->q_id);
+
+ val = hifc_hwif_read_reg(hwif, addr);
+
+ val = AEQ_CTRL_0_CLEAR(val, INTR_IDX) &
+ AEQ_CTRL_0_CLEAR(val, DMA_ATTR) &
+ AEQ_CTRL_0_CLEAR(val, PCI_INTF_IDX) &
+ AEQ_CTRL_0_CLEAR(val, INTR_MODE);
+
+ ctrl0 = AEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) |
+ AEQ_CTRL_0_SET(AEQ_DMA_ATTR_DEFAULT, DMA_ATTR) |
+ AEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) |
+
+ AEQ_CTRL_0_SET(HIFC_INTR_MODE_ARMED, INTR_MODE);
+
+ val |= ctrl0;
+
+ hifc_hwif_write_reg(hwif, addr, val);
+
+ /* set ctrl1 */
+ addr = HIFC_CSR_AEQ_CTRL_1_ADDR(eq->q_id);
+
+ page_size_val = EQ_SET_HW_PAGE_SIZE_VAL(eq);
+ elem_size = EQ_SET_HW_ELEM_SIZE_VAL(eq);
+
+ ctrl1 = AEQ_CTRL_1_SET(eq->eq_len, LEN) |
+ AEQ_CTRL_1_SET(elem_size, ELEM_SIZE) |
+ AEQ_CTRL_1_SET(page_size_val, PAGE_SIZE);
+
+ hifc_hwif_write_reg(hwif, addr, ctrl1);
+
+ } else {
+ ctrl0 = CEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) |
+ CEQ_CTRL_0_SET(CEQ_DMA_ATTR_DEFAULT, DMA_ATTR) |
+ CEQ_CTRL_0_SET(CEQ_LMT_KICK_DEFAULT, LIMIT_KICK) |
+ CEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) |
+ CEQ_CTRL_0_SET(HIFC_INTR_MODE_ARMED, INTR_MODE);
+
+ page_size_val = EQ_SET_HW_PAGE_SIZE_VAL(eq);
+
+ ctrl1 = CEQ_CTRL_1_SET(eq->eq_len, LEN) |
+ CEQ_CTRL_1_SET(page_size_val, PAGE_SIZE);
+
+ /* set ceq ctrl reg through mgmt cpu */
+ err = set_ceq_ctrl_reg(eq->hwdev, eq->q_id, ctrl0, ctrl1);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ceq_elements_init - Initialize all the elements in the ceq
+ * @eq: the event queue
+ * @init_val: value to init with it the elements
+ **/
+static void ceq_elements_init(struct hifc_eq *eq, u32 init_val)
+{
+ u32 i;
+ u32 *ceqe;
+
+ for (i = 0; i < eq->eq_len; i++) {
+ ceqe = GET_CEQ_ELEM(eq, i);
+ *(ceqe) = cpu_to_be32(init_val);
+ }
+
+ wmb(); /* Write the init values */
+}
+
+/**
+ * aeq_elements_init - initialize all the elements in the aeq
+ * @eq: the event queue
+ * @init_val: value to init with it the elements
+ **/
+static void aeq_elements_init(struct hifc_eq *eq, u32 init_val)
+{
+ struct hifc_aeq_elem *aeqe;
+ u32 i;
+
+ for (i = 0; i < eq->eq_len; i++) {
+ aeqe = GET_AEQ_ELEM(eq, i);
+ aeqe->desc = cpu_to_be32(init_val);
+ }
+
+ wmb(); /* Write the init values */
+}
+
+static void free_eq_pages_desc(struct hifc_eq *eq)
+{
+ kfree(eq->virt_addr_for_free);
+ kfree(eq->dma_addr_for_free);
+ kfree(eq->virt_addr);
+ kfree(eq->dma_addr);
+}
+
+static int alloc_eq_pages_desc(struct hifc_eq *eq)
+{
+ u64 dma_addr_size, virt_addr_size;
+ int err;
+
+ dma_addr_size = eq->num_pages * sizeof(*eq->dma_addr);
+ virt_addr_size = eq->num_pages * sizeof(*eq->virt_addr);
+
+ eq->dma_addr = kzalloc(dma_addr_size, GFP_KERNEL);
+ if (!eq->dma_addr)
+ return -ENOMEM;
+
+ eq->virt_addr = kzalloc(virt_addr_size, GFP_KERNEL);
+ if (!eq->virt_addr) {
+ err = -ENOMEM;
+ goto virt_addr_alloc_err;
+ }
+
+ eq->dma_addr_for_free = kzalloc(dma_addr_size, GFP_KERNEL);
+ if (!eq->dma_addr_for_free) {
+ err = -ENOMEM;
+ goto dma_addr_free_alloc_err;
+ }
+
+ eq->virt_addr_for_free = kzalloc(virt_addr_size, GFP_KERNEL);
+ if (!eq->virt_addr_for_free) {
+ err = -ENOMEM;
+ goto virt_addr_free_alloc_err;
+ }
+
+ return 0;
+
+virt_addr_free_alloc_err:
+ kfree(eq->dma_addr_for_free);
+dma_addr_free_alloc_err:
+ kfree(eq->virt_addr);
+virt_addr_alloc_err:
+ kfree(eq->dma_addr);
+ return err;
+}
+
+#define IS_ALIGN(x, a) (((x) & ((a) - 1)) == 0)
+
+static int init_eq_elements(struct hifc_eq *eq)
+{
+ u32 init_val;
+
+ eq->num_elem_in_pg = GET_EQ_NUM_ELEMS(eq, eq->page_size);
+ if (!IS_ALIGN(eq->num_elem_in_pg, eq->num_elem_in_pg)) {
+ sdk_err(eq->hwdev->dev_hdl, "Number element in eq page != power of 2\n");
+ return -EINVAL;
+ }
+
+ init_val = EQ_WRAPPED(eq);
+
+ if (eq->type == HIFC_AEQ)
+ aeq_elements_init(eq, init_val);
+ else
+ ceq_elements_init(eq, init_val);
+
+ return 0;
+}
+
+/**
+ * alloc_eq_pages - allocate the pages for the queue
+ * @eq: the event queue
+ * Return: 0 - success, negative - failure
+ **/
+static int alloc_eq_pages(struct hifc_eq *eq)
+{
+ struct hifc_hwif *hwif = eq->hwdev->hwif;
+ u16 pg_num, i;
+ u32 reg;
+ int err;
+ u8 flag = 0;
+
+ err = alloc_eq_pages_desc(eq);
+ if (err) {
+ sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq pages description\n");
+ return err;
+ }
+
+ for (pg_num = 0; pg_num < eq->num_pages; pg_num++) {
+ eq->virt_addr_for_free[pg_num] = dma_zalloc_coherent
+ (eq->hwdev->dev_hdl, eq->page_size,
+ &eq->dma_addr_for_free[pg_num], GFP_KERNEL);
+ if (!eq->virt_addr_for_free[pg_num]) {
+ err = -ENOMEM;
+ goto dma_alloc_err;
+ }
+
+ eq->dma_addr[pg_num] = eq->dma_addr_for_free[pg_num];
+ eq->virt_addr[pg_num] = eq->virt_addr_for_free[pg_num];
+ if (!IS_ALIGN(eq->dma_addr_for_free[pg_num],
+ eq->page_size)) {
+ sdk_info(eq->hwdev->dev_hdl,
+ "Address is not aligned to %u-bytes as hardware required\n",
+ eq->page_size);
+ sdk_info(eq->hwdev->dev_hdl, "Change eq's page size %u\n",
+ ((eq->page_size) >> 1));
+ eq->dma_addr[pg_num] = ALIGN
+ (eq->dma_addr_for_free[pg_num],
+ (u64)((eq->page_size) >> 1));
+ eq->virt_addr[pg_num] = eq->virt_addr_for_free[pg_num] +
+ ((u64)eq->dma_addr[pg_num]
+ - (u64)eq->dma_addr_for_free[pg_num]);
+ flag = 1;
+ }
+ reg = HIFC_EQ_HI_PHYS_ADDR_REG(eq->type, eq->q_id, pg_num);
+ hifc_hwif_write_reg(hwif, reg,
+ upper_32_bits(eq->dma_addr[pg_num]));
+
+ reg = HIFC_EQ_LO_PHYS_ADDR_REG(eq->type, eq->q_id, pg_num);
+ hifc_hwif_write_reg(hwif, reg,
+ lower_32_bits(eq->dma_addr[pg_num]));
+ }
+
+ if (flag) {
+ eq->page_size = eq->page_size >> 1;
+ eq->eq_len = eq->eq_len >> 1;
+ }
+
+ err = init_eq_elements(eq);
+ if (err) {
+ sdk_err(eq->hwdev->dev_hdl, "Failed to init eq elements\n");
+ goto dma_alloc_err;
+ }
+
+ return 0;
+
+dma_alloc_err:
+ for (i = 0; i < pg_num; i++)
+ dma_free_coherent(eq->hwdev->dev_hdl, eq->page_size,
+ eq->virt_addr_for_free[i],
+ eq->dma_addr_for_free[i]);
+ free_eq_pages_desc(eq);
+ return err;
+}
+
+/**
+ * free_eq_pages - free the pages of the queue
+ * @eq: the event queue
+ **/
+static void free_eq_pages(struct hifc_eq *eq)
+{
+ struct hifc_hwdev *hwdev = eq->hwdev;
+ u16 pg_num;
+
+ for (pg_num = 0; pg_num < eq->num_pages; pg_num++)
+ dma_free_coherent(hwdev->dev_hdl, eq->orig_page_size,
+ eq->virt_addr_for_free[pg_num],
+ eq->dma_addr_for_free[pg_num]);
+
+ free_eq_pages_desc(eq);
+}
+
+static inline u32 get_page_size(struct hifc_eq *eq)
+{
+ u32 total_size;
+ u16 count, n = 0;
+
+ total_size = ALIGN((eq->eq_len * eq->elem_size), EQ_MIN_PAGE_SIZE);
+
+ if (total_size <= (HIFC_EQ_MAX_PAGES * EQ_MIN_PAGE_SIZE))
+ return EQ_MIN_PAGE_SIZE;
+
+ count = (u16)(ALIGN((total_size / HIFC_EQ_MAX_PAGES),
+ EQ_MIN_PAGE_SIZE) / EQ_MIN_PAGE_SIZE);
+
+ if (!(count & (count - 1)))
+ return EQ_MIN_PAGE_SIZE * count;
+
+ while (count) {
+ count >>= 1;
+ n++;
+ }
+
+ return EQ_MIN_PAGE_SIZE << n;
+}
+
+static int request_eq_irq(struct hifc_eq *eq, enum hifc_eq_type type,
+ struct irq_info *entry)
+{
+ int err = 0;
+
+ if (type == HIFC_AEQ) {
+ struct hifc_eq_work *aeq_work = &eq->aeq_work;
+
+ INIT_WORK(&aeq_work->work, eq_irq_work);
+ } else {
+ tasklet_init(&eq->ceq_tasklet, ceq_tasklet,
+ (ulong)(&eq->ceq_tasklet_data));
+ }
+
+ if (type == HIFC_AEQ) {
+ snprintf(eq->irq_name, sizeof(eq->irq_name),
+ "hifc_aeq%d@pci:%s", eq->q_id,
+ pci_name(eq->hwdev->pcidev_hdl));
+
+ err = request_irq(entry->irq_id, aeq_interrupt, 0UL,
+ eq->irq_name, eq);
+ } else {
+ snprintf(eq->irq_name, sizeof(eq->irq_name),
+ "hifc_ceq%d@pci:%s", eq->q_id,
+ pci_name(eq->hwdev->pcidev_hdl));
+
+ err = request_irq(entry->irq_id, ceq_interrupt, 0UL,
+ eq->irq_name, eq);
+ }
+
+ return err;
+}
+
+/**
+ * init_eq - initialize eq
+ * @eq: the event queue
+ * @hwdev: the pointer to hw device
+ * @q_id: Queue id number
+ * @q_len: the number of EQ elements
+ * @type: the type of the event queue, ceq or aeq
+ * @entry: msix entry associated with the event queue
+ * Return: 0 - Success, Negative - failure
+ **/
+static int init_eq(struct hifc_eq *eq, struct hifc_hwdev *hwdev, u16 q_id,
+ u32 q_len, enum hifc_eq_type type, struct irq_info *entry)
+{
+ int err = 0;
+
+ eq->hwdev = hwdev;
+ eq->q_id = q_id;
+ eq->type = type;
+ eq->eq_len = q_len;
+
+ /* clear eq_len to force eqe drop in hardware */
+ if (eq->type == HIFC_AEQ)
+ hifc_hwif_write_reg(eq->hwdev->hwif,
+ HIFC_CSR_AEQ_CTRL_1_ADDR(eq->q_id), 0);
+ else
+ set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0);
+
+ eq->cons_idx = 0;
+ eq->wrapped = 0;
+
+ eq->elem_size = (type == HIFC_AEQ) ?
+ HIFC_AEQE_SIZE : HIFC_CEQE_SIZE;
+
+ eq->page_size = get_page_size(eq);
+ eq->orig_page_size = eq->page_size;
+ eq->num_pages = GET_EQ_NUM_PAGES(eq, eq->page_size);
+ if (eq->num_pages > HIFC_EQ_MAX_PAGES) {
+ sdk_err(hwdev->dev_hdl, "Number pages:%d too many pages for eq\n",
+ eq->num_pages);
+ return -EINVAL;
+ }
+
+ err = alloc_eq_pages(eq);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to allocate pages for eq\n");
+ return err;
+ }
+
+ eq->eq_irq.msix_entry_idx = entry->msix_entry_idx;
+ eq->eq_irq.irq_id = entry->irq_id;
+
+ err = set_eq_ctrls(eq);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to allocate pages for eq\n");
+ goto init_eq_ctrls_err;
+ }
+
+ hifc_hwif_write_reg(eq->hwdev->hwif, EQ_PROD_IDX_REG_ADDR(eq), 0);
+ set_eq_cons_idx(eq, HIFC_EQ_ARMED);
+
+ err = request_eq_irq(eq, type, entry);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to request irq for the eq, err: %d\n",
+ err);
+ goto req_irq_err;
+ }
+
+ hifc_set_msix_state(hwdev, entry->msix_entry_idx, HIFC_MSIX_ENABLE);
+
+ return 0;
+
+init_eq_ctrls_err:
+req_irq_err:
+ free_eq_pages(eq);
+ return err;
+}
+
+/**
+ * remove_eq - remove eq
+ * @eq: the event queue
+ **/
+static void remove_eq(struct hifc_eq *eq)
+{
+ struct irq_info *entry = &eq->eq_irq;
+
+ hifc_set_msix_state(eq->hwdev, entry->msix_entry_idx,
+ HIFC_MSIX_DISABLE);
+ synchronize_irq(entry->irq_id);
+
+ free_irq(entry->irq_id, eq);
+
+ if (eq->type == HIFC_AEQ) {
+ struct hifc_eq_work *aeq_work = &eq->aeq_work;
+
+ cancel_work_sync(&aeq_work->work);
+
+ /* clear eq_len to avoid hw access host memory */
+ hifc_hwif_write_reg(eq->hwdev->hwif,
+ HIFC_CSR_AEQ_CTRL_1_ADDR(eq->q_id), 0);
+ } else {
+ tasklet_kill(&eq->ceq_tasklet);
+
+ set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0);
+ }
+
+ /* update cons_idx to avoid invalid interrupt */
+ eq->cons_idx = hifc_hwif_read_reg(eq->hwdev->hwif,
+ EQ_PROD_IDX_REG_ADDR(eq));
+ set_eq_cons_idx(eq, HIFC_EQ_NOT_ARMED);
+
+ free_eq_pages(eq);
+}
+
+/**
+ * hifc_aeqs_init - init all the aeqs
+ * @hwdev: the pointer to hw device
+ * @num_ceqs: number of AEQs
+ * @msix_entries: msix entries associated with the event queues
+ * Return: 0 - Success, Negative - failure
+ **/
+int hifc_aeqs_init(struct hifc_hwdev *hwdev, u16 num_aeqs,
+ struct irq_info *msix_entries)
+{
+ struct hifc_aeqs *aeqs;
+ int err;
+ u16 i, q_id;
+
+ aeqs = kzalloc(sizeof(*aeqs), GFP_KERNEL);
+ if (!aeqs)
+ return -ENOMEM;
+
+ hwdev->aeqs = aeqs;
+ aeqs->hwdev = hwdev;
+ aeqs->num_aeqs = num_aeqs;
+
+ aeqs->workq = create_singlethread_workqueue(HIFC_EQS_WQ_NAME);
+ if (!aeqs->workq) {
+ sdk_err(hwdev->dev_hdl, "Failed to initialize aeq workqueue\n");
+ err = -ENOMEM;
+ goto create_work_err;
+ }
+
+ if (g_aeq_len < HIFC_MIN_AEQ_LEN || g_aeq_len > HIFC_MAX_AEQ_LEN) {
+ sdk_warn(hwdev->dev_hdl, "Module Parameter g_aeq_len value %d out of range, resetting to %d\n",
+ g_aeq_len, HIFC_DEFAULT_AEQ_LEN);
+ g_aeq_len = HIFC_DEFAULT_AEQ_LEN;
+ }
+
+ for (q_id = 0; q_id < num_aeqs; q_id++) {
+ err = init_eq(&aeqs->aeq[q_id], hwdev, q_id, g_aeq_len,
+ HIFC_AEQ, &msix_entries[q_id]);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init aeq %d\n",
+ q_id);
+ goto init_aeq_err;
+ }
+ }
+
+ return 0;
+
+init_aeq_err:
+ for (i = 0; i < q_id; i++)
+ remove_eq(&aeqs->aeq[i]);
+
+ destroy_workqueue(aeqs->workq);
+
+create_work_err:
+ kfree(aeqs);
+
+ return err;
+}
+
+/**
+ * hifc_aeqs_free - free all the aeqs
+ * @hwdev: the pointer to hw device
+ **/
+void hifc_aeqs_free(struct hifc_hwdev *hwdev)
+{
+ struct hifc_aeqs *aeqs = hwdev->aeqs;
+ enum hifc_aeq_type aeq_event = HIFC_HW_INTER_INT;
+ enum hifc_aeq_sw_type sw_aeq_event = HIFC_STATELESS_EVENT;
+ u16 q_id;
+
+ for (q_id = 0; q_id < aeqs->num_aeqs; q_id++)
+ remove_eq(&aeqs->aeq[q_id]);
+
+ for (; sw_aeq_event < HIFC_MAX_AEQ_SW_EVENTS; sw_aeq_event++)
+ hifc_aeq_unregister_swe_cb(hwdev, sw_aeq_event);
+
+ for (; aeq_event < HIFC_MAX_AEQ_EVENTS; aeq_event++)
+ hifc_aeq_unregister_hw_cb(hwdev, aeq_event);
+
+ destroy_workqueue(aeqs->workq);
+
+ kfree(aeqs);
+}
+
+/**
+ * hifc_ceqs_init - init all the ceqs
+ * @hwdev: the pointer to hw device
+ * @num_ceqs: number of CEQs
+ * @msix_entries: msix entries associated with the event queues
+ * Return: 0 - Success, Negative - failure
+ **/
+int hifc_ceqs_init(struct hifc_hwdev *hwdev, u16 num_ceqs,
+ struct irq_info *msix_entries)
+{
+ struct hifc_ceqs *ceqs;
+ int err;
+ u16 i, q_id;
+
+ ceqs = kzalloc(sizeof(*ceqs), GFP_KERNEL);
+ if (!ceqs)
+ return -ENOMEM;
+
+ hwdev->ceqs = ceqs;
+
+ ceqs->hwdev = hwdev;
+ ceqs->num_ceqs = num_ceqs;
+
+ if (g_ceq_len < HIFC_MIN_CEQ_LEN || g_ceq_len > HIFC_MAX_CEQ_LEN) {
+ sdk_warn(hwdev->dev_hdl, "Module Parameter g_ceq_len value %d out of range, resetting to %d\n",
+ g_ceq_len, HIFC_DEFAULT_CEQ_LEN);
+ g_ceq_len = HIFC_DEFAULT_CEQ_LEN;
+ }
+
+ if (!g_num_ceqe_in_tasklet) {
+ sdk_warn(hwdev->dev_hdl, "Module Parameter g_num_ceqe_in_tasklet can not be zero, resetting to %d\n",
+ HIFC_TASK_PROCESS_EQE_LIMIT);
+ g_num_ceqe_in_tasklet = HIFC_TASK_PROCESS_EQE_LIMIT;
+ }
+
+ for (q_id = 0; q_id < num_ceqs; q_id++) {
+ err = init_eq(&ceqs->ceq[q_id], hwdev, q_id, g_ceq_len,
+ HIFC_CEQ, &msix_entries[q_id]);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init ceq %d\n",
+ q_id);
+ goto init_ceq_err;
+ }
+ }
+
+ return 0;
+
+init_ceq_err:
+ for (i = 0; i < q_id; i++)
+ remove_eq(&ceqs->ceq[i]);
+
+ kfree(ceqs);
+
+ return err;
+}
+
+/**
+ * hifc_ceqs_free - free all the ceqs
+ * @hwdev: the pointer to hw device
+ **/
+void hifc_ceqs_free(struct hifc_hwdev *hwdev)
+{
+ struct hifc_ceqs *ceqs = hwdev->ceqs;
+ enum hifc_ceq_event ceq_event = HIFC_CMDQ;
+ u16 q_id;
+
+ for (q_id = 0; q_id < ceqs->num_ceqs; q_id++)
+ remove_eq(&ceqs->ceq[q_id]);
+
+ for (; ceq_event < HIFC_MAX_CEQ_EVENTS; ceq_event++)
+ hifc_ceq_unregister_cb(hwdev, ceq_event);
+
+ kfree(ceqs);
+}
+
+void hifc_get_ceq_irqs(struct hifc_hwdev *hwdev, struct irq_info *irqs,
+ u16 *num_irqs)
+{
+ struct hifc_ceqs *ceqs = hwdev->ceqs;
+ u16 q_id;
+
+ for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) {
+ irqs[q_id].irq_id = ceqs->ceq[q_id].eq_irq.irq_id;
+ irqs[q_id].msix_entry_idx =
+ ceqs->ceq[q_id].eq_irq.msix_entry_idx;
+ }
+
+ *num_irqs = ceqs->num_ceqs;
+}
+
+void hifc_get_aeq_irqs(struct hifc_hwdev *hwdev, struct irq_info *irqs,
+ u16 *num_irqs)
+{
+ struct hifc_aeqs *aeqs = hwdev->aeqs;
+ u16 q_id;
+
+ for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) {
+ irqs[q_id].irq_id = aeqs->aeq[q_id].eq_irq.irq_id;
+ irqs[q_id].msix_entry_idx =
+ aeqs->aeq[q_id].eq_irq.msix_entry_idx;
+ }
+
+ *num_irqs = aeqs->num_aeqs;
+}
+
+void hifc_dump_aeq_info(struct hifc_hwdev *hwdev)
+{
+ struct hifc_aeq_elem *aeqe_pos;
+ struct hifc_eq *eq;
+ u32 addr, ci, pi;
+ int q_id;
+
+ for (q_id = 0; q_id < hwdev->aeqs->num_aeqs; q_id++) {
+ eq = &hwdev->aeqs->aeq[q_id];
+ addr = EQ_CONS_IDX_REG_ADDR(eq);
+ ci = hifc_hwif_read_reg(hwdev->hwif, addr);
+ addr = EQ_PROD_IDX_REG_ADDR(eq);
+ pi = hifc_hwif_read_reg(hwdev->hwif, addr);
+ aeqe_pos = GET_CURR_AEQ_ELEM(eq);
+ sdk_err(hwdev->dev_hdl, "Aeq id: %d, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %d, desc: 0x%x\n",
+ q_id, ci, pi, work_busy(&eq->aeq_work.work),
+ eq->wrapped, be32_to_cpu(aeqe_pos->desc));
+ }
+}
+
diff --git a/drivers/scsi/huawei/hifc/hifc_eqs.h b/drivers/scsi/huawei/hifc/hifc_eqs.h
new file mode 100644
index 000000000000..2dcfc432c8f2
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_eqs.h
@@ -0,0 +1,233 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ */
+
+#ifndef HIFC_EQS_H
+#define HIFC_EQS_H
+
+#define HIFC_MAX_AEQS 3
+#define HIFC_MAX_CEQS 32
+
+#define HIFC_EQ_MAX_PAGES 8
+
+#define HIFC_AEQE_SIZE 64
+#define HIFC_CEQE_SIZE 4
+
+#define HIFC_AEQE_DESC_SIZE 4
+#define HIFC_AEQE_DATA_SIZE \
+ (HIFC_AEQE_SIZE - HIFC_AEQE_DESC_SIZE)
+
+#define HIFC_DEFAULT_AEQ_LEN 4096
+#define HIFC_DEFAULT_CEQ_LEN 8192
+
+#define HIFC_MIN_AEQ_LEN 64
+#define HIFC_MAX_AEQ_LEN (512 * 1024)
+#define HIFC_MIN_CEQ_LEN 64
+#define HIFC_MAX_CEQ_LEN (1024 * 1024)
+
+#define HIFC_CEQ_ID_CMDQ 0
+#define EQ_IRQ_NAME_LEN 64
+
+/* EQ registers */
+#define HIFC_AEQ_MTT_OFF_BASE_ADDR 0x200
+#define HIFC_CEQ_MTT_OFF_BASE_ADDR 0x400
+
+#define HIFC_EQ_MTT_OFF_STRIDE 0x40
+
+#define HIFC_CSR_AEQ_MTT_OFF(id) \
+ (HIFC_AEQ_MTT_OFF_BASE_ADDR + (id) * HIFC_EQ_MTT_OFF_STRIDE)
+
+#define HIFC_CSR_CEQ_MTT_OFF(id) \
+ (HIFC_CEQ_MTT_OFF_BASE_ADDR + (id) * HIFC_EQ_MTT_OFF_STRIDE)
+
+#define HIFC_CSR_EQ_PAGE_OFF_STRIDE 8
+
+#define HIFC_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num) \
+ (HIFC_CSR_AEQ_MTT_OFF(q_id) + \
+ (pg_num) * HIFC_CSR_EQ_PAGE_OFF_STRIDE)
+
+#define HIFC_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num) \
+ (HIFC_CSR_AEQ_MTT_OFF(q_id) + \
+ (pg_num) * HIFC_CSR_EQ_PAGE_OFF_STRIDE + 4)
+
+#define HIFC_CEQ_HI_PHYS_ADDR_REG(q_id, pg_num) \
+ (HIFC_CSR_CEQ_MTT_OFF(q_id) + \
+ (pg_num) * HIFC_CSR_EQ_PAGE_OFF_STRIDE)
+
+#define HIFC_CEQ_LO_PHYS_ADDR_REG(q_id, pg_num) \
+ (HIFC_CSR_CEQ_MTT_OFF(q_id) + \
+ (pg_num) * HIFC_CSR_EQ_PAGE_OFF_STRIDE + 4)
+
+#define HIFC_EQ_HI_PHYS_ADDR_REG(type, q_id, pg_num) \
+ ((u32)((type == HIFC_AEQ) ? \
+ HIFC_AEQ_HI_PHYS_ADDR_REG(q_id, pg_num) : \
+ HIFC_CEQ_HI_PHYS_ADDR_REG(q_id, pg_num)))
+
+#define HIFC_EQ_LO_PHYS_ADDR_REG(type, q_id, pg_num) \
+ ((u32)((type == HIFC_AEQ) ? \
+ HIFC_AEQ_LO_PHYS_ADDR_REG(q_id, pg_num) : \
+ HIFC_CEQ_LO_PHYS_ADDR_REG(q_id, pg_num)))
+
+#define HIFC_AEQ_CTRL_0_ADDR_BASE 0xE00
+#define HIFC_AEQ_CTRL_1_ADDR_BASE 0xE04
+#define HIFC_AEQ_CONS_IDX_0_ADDR_BASE 0xE08
+#define HIFC_AEQ_CONS_IDX_1_ADDR_BASE 0xE0C
+
+#define HIFC_EQ_OFF_STRIDE 0x80
+
+#define HIFC_CSR_AEQ_CTRL_0_ADDR(idx) \
+ (HIFC_AEQ_CTRL_0_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CSR_AEQ_CTRL_1_ADDR(idx) \
+ (HIFC_AEQ_CTRL_1_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CSR_AEQ_CONS_IDX_ADDR(idx) \
+ (HIFC_AEQ_CONS_IDX_0_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CSR_AEQ_PROD_IDX_ADDR(idx) \
+ (HIFC_AEQ_CONS_IDX_1_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CEQ_CTRL_0_ADDR_BASE 0x1000
+#define HIFC_CEQ_CTRL_1_ADDR_BASE 0x1004
+#define HIFC_CEQ_CONS_IDX_0_ADDR_BASE 0x1008
+#define HIFC_CEQ_CONS_IDX_1_ADDR_BASE 0x100C
+
+#define HIFC_CSR_CEQ_CTRL_0_ADDR(idx) \
+ (HIFC_CEQ_CTRL_0_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CSR_CEQ_CTRL_1_ADDR(idx) \
+ (HIFC_CEQ_CTRL_1_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CSR_CEQ_CONS_IDX_ADDR(idx) \
+ (HIFC_CEQ_CONS_IDX_0_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+#define HIFC_CSR_CEQ_PROD_IDX_ADDR(idx) \
+ (HIFC_CEQ_CONS_IDX_1_ADDR_BASE + (idx) * HIFC_EQ_OFF_STRIDE)
+
+enum hifc_eq_type {
+ HIFC_AEQ,
+ HIFC_CEQ
+};
+
+enum hifc_eq_intr_mode {
+ HIFC_INTR_MODE_ARMED,
+ HIFC_INTR_MODE_ALWAYS,
+};
+
+enum hifc_eq_ci_arm_state {
+ HIFC_EQ_NOT_ARMED,
+ HIFC_EQ_ARMED,
+};
+
+struct hifc_eq_work {
+ struct work_struct work;
+ void *data;
+};
+
+struct hifc_ceq_tasklet_data {
+ void *data;
+};
+
+struct hifc_eq {
+ struct hifc_hwdev *hwdev;
+ u16 q_id;
+ enum hifc_eq_type type;
+ u32 page_size;
+ u32 orig_page_size;
+ u32 eq_len;
+
+ u32 cons_idx;
+ u16 wrapped;
+
+ u16 elem_size;
+ u16 num_pages;
+ u32 num_elem_in_pg;
+
+ struct irq_info eq_irq;
+ char irq_name[EQ_IRQ_NAME_LEN];
+
+ dma_addr_t *dma_addr;
+ u8 **virt_addr;
+ dma_addr_t *dma_addr_for_free;
+ u8 **virt_addr_for_free;
+
+ struct hifc_eq_work aeq_work;
+ struct tasklet_struct ceq_tasklet;
+ struct hifc_ceq_tasklet_data ceq_tasklet_data;
+
+ u64 hard_intr_jif;
+ u64 soft_intr_jif;
+};
+
+struct hifc_aeq_elem {
+ u8 aeqe_data[HIFC_AEQE_DATA_SIZE];
+ u32 desc;
+};
+
+enum hifc_aeq_cb_state {
+ HIFC_AEQ_HW_CB_REG = 0,
+ HIFC_AEQ_HW_CB_RUNNING,
+ HIFC_AEQ_SW_CB_REG,
+ HIFC_AEQ_SW_CB_RUNNING,
+};
+
+struct hifc_aeqs {
+ struct hifc_hwdev *hwdev;
+
+ hifc_aeq_hwe_cb aeq_hwe_cb[HIFC_MAX_AEQ_EVENTS];
+ hifc_aeq_swe_cb aeq_swe_cb[HIFC_MAX_AEQ_SW_EVENTS];
+ unsigned long aeq_hw_cb_state[HIFC_MAX_AEQ_EVENTS];
+ unsigned long aeq_sw_cb_state[HIFC_MAX_AEQ_SW_EVENTS];
+
+ struct hifc_eq aeq[HIFC_MAX_AEQS];
+ u16 num_aeqs;
+
+ struct workqueue_struct *workq;
+};
+
+enum hifc_ceq_cb_state {
+ HIFC_CEQ_CB_REG = 0,
+ HIFC_CEQ_CB_RUNNING,
+};
+
+struct hifc_ceqs {
+ struct hifc_hwdev *hwdev;
+
+ hifc_ceq_event_cb ceq_cb[HIFC_MAX_CEQ_EVENTS];
+ void *ceq_data[HIFC_MAX_CEQ_EVENTS];
+ unsigned long ceq_cb_state[HIFC_MAX_CEQ_EVENTS];
+
+ struct hifc_eq ceq[HIFC_MAX_CEQS];
+ u16 num_ceqs;
+};
+
+int hifc_aeqs_init(struct hifc_hwdev *hwdev, u16 num_aeqs,
+ struct irq_info *msix_entries);
+
+void hifc_aeqs_free(struct hifc_hwdev *hwdev);
+
+int hifc_ceqs_init(struct hifc_hwdev *hwdev, u16 num_ceqs,
+ struct irq_info *msix_entries);
+
+void hifc_ceqs_free(struct hifc_hwdev *hwdev);
+
+void hifc_get_ceq_irqs(struct hifc_hwdev *hwdev, struct irq_info *irqs,
+ u16 *num_irqs);
+
+void hifc_get_aeq_irqs(struct hifc_hwdev *hwdev, struct irq_info *irqs,
+ u16 *num_irqs);
+
+void hifc_dump_aeq_info(struct hifc_hwdev *hwdev);
+
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_hw.h b/drivers/scsi/huawei/hifc/hifc_hw.h
new file mode 100644
index 000000000000..49b2edd2bac6
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_hw.h
@@ -0,0 +1,611 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_HW_H_
+#define HIFC_HW_H_
+
+#ifndef __BIG_ENDIAN__
+#define __BIG_ENDIAN__ 0x4321
+#endif
+
+#ifndef __LITTLE_ENDIAN__
+#define __LITTLE_ENDIAN__ 0x1234
+#endif
+
+enum hifc_mod_type {
+ HIFC_MOD_COMM = 0, /* HW communication module */
+ HIFC_MOD_L2NIC = 1, /* L2NIC module*/
+ HIFC_MOD_FCOE = 6,
+ HIFC_MOD_CFGM = 7, /* Configuration module */
+ HIFC_MOD_FC = 10,
+ HIFC_MOD_HILINK = 14,
+ HIFC_MOD_HW_MAX = 16, /* hardware max module id */
+
+ /* Software module id, for PF/VF and multi-host */
+ HIFC_MOD_MAX,
+};
+
+struct hifc_cmd_buf {
+ void *buf;
+ dma_addr_t dma_addr;
+ u16 size;
+};
+
+enum hifc_ack_type {
+ HIFC_ACK_TYPE_CMDQ,
+ HIFC_ACK_TYPE_SHARE_CQN,
+ HIFC_ACK_TYPE_APP_CQN,
+ HIFC_MOD_ACK_MAX = 15,
+};
+
+int hifc_msg_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size, u32 timeout);
+
+/* PF/VF send msg to uP by api cmd, and return immediately */
+int hifc_msg_to_mgmt_async(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size);
+
+int hifc_api_cmd_write_nack(void *hwdev, u8 dest,
+ void *cmd, u16 size);
+
+int hifc_api_cmd_read_ack(void *hwdev, u8 dest,
+ void *cmd, u16 size, void *ack, u16 ack_size);
+/* PF/VF send cmd to ucode by cmdq, and return if success.
+ * timeout=0, use default timeout.
+ */
+int hifc_cmdq_direct_resp(void *hwdev, enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in,
+ u64 *out_param, u32 timeout);
+/* 1. whether need the timeout parameter
+ * 2. out_param indicates the status of the microcode processing command
+ */
+
+/* PF/VF send cmd to ucode by cmdq, and return detailed result.
+ * timeout=0, use default timeout.
+ */
+int hifc_cmdq_detail_resp(void *hwdev, enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in,
+ struct hifc_cmd_buf *buf_out, u32 timeout);
+
+/* PF/VF send cmd to ucode by cmdq, and return immediately
+ */
+int hifc_cmdq_async(void *hwdev, enum hifc_ack_type ack_type,
+ enum hifc_mod_type mod, u8 cmd,
+ struct hifc_cmd_buf *buf_in);
+
+int hifc_ppf_tmr_start(void *hwdev);
+int hifc_ppf_tmr_stop(void *hwdev);
+
+enum hifc_ceq_event {
+ HIFC_CMDQ = 3,
+ HIFC_MAX_CEQ_EVENTS = 6,
+};
+
+typedef void (*hifc_ceq_event_cb)(void *handle, u32 ceqe_data);
+int hifc_ceq_register_cb(void *hwdev, enum hifc_ceq_event event,
+ hifc_ceq_event_cb callback);
+void hifc_ceq_unregister_cb(void *hwdev, enum hifc_ceq_event event);
+
+enum hifc_aeq_type {
+ HIFC_HW_INTER_INT = 0,
+ HIFC_MBX_FROM_FUNC = 1,
+ HIFC_MSG_FROM_MGMT_CPU = 2,
+ HIFC_API_RSP = 3,
+ HIFC_API_CHAIN_STS = 4,
+ HIFC_MBX_SEND_RSLT = 5,
+ HIFC_MAX_AEQ_EVENTS
+};
+
+enum hifc_aeq_sw_type {
+ HIFC_STATELESS_EVENT = 0,
+ HIFC_STATEFULL_EVENT = 1,
+ HIFC_MAX_AEQ_SW_EVENTS
+};
+
+typedef void (*hifc_aeq_hwe_cb)(void *handle, u8 *data, u8 size);
+int hifc_aeq_register_hw_cb(void *hwdev, enum hifc_aeq_type event,
+ hifc_aeq_hwe_cb hwe_cb);
+void hifc_aeq_unregister_hw_cb(void *hwdev, enum hifc_aeq_type event);
+
+typedef u8 (*hifc_aeq_swe_cb)(void *handle, u8 event, u64 data);
+int hifc_aeq_register_swe_cb(void *hwdev, enum hifc_aeq_sw_type event,
+ hifc_aeq_swe_cb aeq_swe_cb);
+void hifc_aeq_unregister_swe_cb(void *hwdev, enum hifc_aeq_sw_type event);
+
+typedef void (*hifc_mgmt_msg_cb)(void *hwdev, void *pri_handle,
+ u8 cmd, void *buf_in, u16 in_size, void *buf_out, u16 *out_size);
+
+int hifc_register_mgmt_msg_cb(void *hwdev,
+ enum hifc_mod_type mod, void *pri_handle,
+ hifc_mgmt_msg_cb callback);
+void hifc_unregister_mgmt_msg_cb(void *hwdev, enum hifc_mod_type mod);
+
+struct hifc_cmd_buf *hifc_alloc_cmd_buf(void *hwdev);
+void hifc_free_cmd_buf(void *hwdev, struct hifc_cmd_buf *buf);
+
+int hifc_alloc_db_addr(void *hwdev, void __iomem **db_base,
+ void __iomem **dwqe_base);
+void hifc_free_db_addr(void *hwdev, void __iomem *db_base,
+ void __iomem *dwqe_base);
+
+struct nic_interrupt_info {
+ u32 lli_set;
+ u32 interrupt_coalesc_set;
+ u16 msix_index;
+ u8 lli_credit_limit;
+ u8 lli_timer_cfg;
+ u8 pending_limt;
+ u8 coalesc_timer_cfg;
+ u8 resend_timer_cfg;
+};
+
+int hifc_get_interrupt_cfg(void *hwdev,
+ struct nic_interrupt_info *interrupt_info);
+
+int hifc_set_interrupt_cfg(void *hwdev,
+ struct nic_interrupt_info interrupt_info);
+
+/* The driver code implementation interface*/
+void hifc_misx_intr_clear_resend_bit(void *hwdev,
+ u16 msix_idx, u8 clear_resend_en);
+
+struct hifc_sq_attr {
+ u8 dma_attr_off;
+ u8 pending_limit;
+ u8 coalescing_time;
+ u8 intr_en;
+ u16 intr_idx;
+ u32 l2nic_sqn;
+ u64 ci_dma_base;
+};
+
+int hifc_set_ci_table(void *hwdev, u16 q_id, struct hifc_sq_attr *attr);
+
+int hifc_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz);
+int hifc_clean_root_ctxt(void *hwdev);
+void hifc_record_pcie_error(void *hwdev);
+
+int hifc_func_rx_tx_flush(void *hwdev);
+
+int hifc_func_tmr_bitmap_set(void *hwdev, bool enable);
+
+struct hifc_init_para {
+ /* Record hifc_pcidev or NDIS_Adapter pointer address*/
+ void *adapter_hdl;
+ /* Record pcidev or Handler pointer address
+ * for example: ioremap interface input parameter
+ */
+ void *pcidev_hdl;
+ /* Record pcidev->dev or Handler pointer address which used to
+ * dma address application or dev_err print the parameter
+ */
+ void *dev_hdl;
+
+ void *cfg_reg_base; /* Configure virtual address, bar0/1*/
+ /* interrupt configuration register address, bar2/3 */
+ void *intr_reg_base;
+ u64 db_base_phy;
+ void *db_base; /* the doorbell address, bar4/5 higher 4M space*/
+ void *dwqe_mapping;/* direct wqe 4M, follow the doorbell address space*/
+ void **hwdev;
+ void *chip_node;
+ /* In bmgw x86 host, driver can't send message to mgmt cpu directly,
+ * need to trasmit message ppf mbox to bmgw arm host.
+ */
+ void *ppf_hwdev;
+};
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+#define MAX_FUNCTION_NUM 512
+#define HIFC_MAX_PF_NUM 16
+#define HIFC_MAX_COS 8
+#define INIT_FAILED 0
+#define INIT_SUCCESS 1
+#define MAX_DRV_BUF_SIZE 4096
+
+struct hifc_cmd_get_light_module_abs {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 port_id;
+ u8 abs_status; /* 0:present, 1:absent */
+ u8 rsv[2];
+};
+
+#define SFP_INFO_MAX_SIZE 512
+struct hifc_cmd_get_sfp_qsfp_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 port_id;
+ u8 wire_type;
+ u16 out_len;
+ u8 sfp_qsfp_info[SFP_INFO_MAX_SIZE];
+};
+
+#define HIFC_MAX_PORT_ID 4
+
+struct hifc_port_routine_cmd {
+ bool up_send_sfp_info;
+ bool up_send_sfp_abs;
+
+ struct hifc_cmd_get_sfp_qsfp_info sfp_info;
+ struct hifc_cmd_get_light_module_abs abs;
+};
+
+struct card_node {
+ struct list_head node;
+ struct list_head func_list;
+ char chip_name[IFNAMSIZ];
+ void *log_info;
+ void *dbgtool_info;
+ void *func_handle_array[MAX_FUNCTION_NUM];
+ unsigned char dp_bus_num;
+ u8 func_num;
+ struct attribute dbgtool_attr_file;
+
+ bool cos_up_setted;
+ u8 cos_up[HIFC_MAX_COS];
+ bool ppf_state;
+ u8 pf_bus_num[HIFC_MAX_PF_NUM];
+
+ struct hifc_port_routine_cmd rt_cmd[HIFC_MAX_PORT_ID];
+
+ /* mutex used for copy sfp info */
+ struct mutex sfp_mutex;
+};
+
+enum hifc_hwdev_init_state {
+ HIFC_HWDEV_NONE_INITED = 0,
+ HIFC_HWDEV_CLP_INITED,
+ HIFC_HWDEV_AEQ_INITED,
+ HIFC_HWDEV_MGMT_INITED,
+ HIFC_HWDEV_MBOX_INITED,
+ HIFC_HWDEV_CMDQ_INITED,
+ HIFC_HWDEV_COMM_CH_INITED,
+ HIFC_HWDEV_ALL_INITED,
+ HIFC_HWDEV_MAX_INVAL_INITED
+};
+
+enum hifc_func_cap {
+ /* send message to mgmt cpu directly */
+ HIFC_FUNC_MGMT = 1 << 0,
+ /* setting port attribute, pause/speed etc. */
+ HIFC_FUNC_PORT = 1 << 1,
+ /* Enable SR-IOV in default */
+ HIFC_FUNC_SRIOV_EN_DFLT = 1 << 2,
+ /* Can't change VF num */
+ HIFC_FUNC_SRIOV_NUM_FIX = 1 << 3,
+ /* Fcorce pf/vf link up */
+ HIFC_FUNC_FORCE_LINK_UP = 1 << 4,
+ /* Support rate limit */
+ HIFC_FUNC_SUPP_RATE_LIMIT = 1 << 5,
+ HIFC_FUNC_SUPP_DFX_REG = 1 << 6,
+ /* Support promisc/multicast/all-multi */
+ HIFC_FUNC_SUPP_RX_MODE = 1 << 7,
+ /* Set vf mac and vlan by ip link */
+ HIFC_FUNC_SUPP_SET_VF_MAC_VLAN = 1 << 8,
+ /* Support set mac by ifconfig */
+ HIFC_FUNC_SUPP_CHANGE_MAC = 1 << 9,
+ /* OVS don't support SCTP_CRC/HW_VLAN/LRO */
+ HIFC_FUNC_OFFLOAD_OVS_UNSUPP = 1 << 10,
+};
+
+#define FUNC_SUPPORT_MGMT(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & HIFC_FUNC_MGMT))
+#define FUNC_SUPPORT_PORT_SETTING(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & HIFC_FUNC_PORT))
+#define FUNC_SUPPORT_DCB(hwdev) \
+ (FUNC_SUPPORT_PORT_SETTING(hwdev))
+#define FUNC_ENABLE_SRIOV_IN_DEFAULT(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_SRIOV_EN_DFLT))
+#define FUNC_SRIOV_FIX_NUM_VF(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_SRIOV_NUM_FIX))
+#define FUNC_SUPPORT_RX_MODE(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_SUPP_RX_MODE))
+#define FUNC_SUPPORT_RATE_LIMIT(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_SUPP_RATE_LIMIT))
+#define FUNC_SUPPORT_SET_VF_MAC_VLAN(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_SUPP_SET_VF_MAC_VLAN))
+#define FUNC_SUPPORT_CHANGE_MAC(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_SUPP_CHANGE_MAC))
+#define FUNC_FORCE_LINK_UP(hwdev) \
+ (!!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_FORCE_LINK_UP))
+#define FUNC_SUPPORT_SCTP_CRC(hwdev) \
+ (!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_OFFLOAD_OVS_UNSUPP))
+#define FUNC_SUPPORT_HW_VLAN(hwdev) \
+ (!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_OFFLOAD_OVS_UNSUPP))
+#define FUNC_SUPPORT_LRO(hwdev) \
+ (!(hifc_get_func_feature_cap(hwdev) & \
+ HIFC_FUNC_OFFLOAD_OVS_UNSUPP))
+
+int hifc_init_hwdev(struct hifc_init_para *para);
+void hifc_free_hwdev(void *hwdev);
+int hifc_stateful_init(void *hwdev);
+void hifc_stateful_deinit(void *hwdev);
+bool hifc_is_hwdev_mod_inited(void *hwdev, enum hifc_hwdev_init_state state);
+u64 hifc_get_func_feature_cap(void *hwdev);
+int hifc_slq_init(void *dev, int num_wqs);
+void hifc_slq_uninit(void *dev);
+int hifc_slq_alloc(void *dev, u16 wqebb_size, u16 q_depth,
+ u16 page_size, u64 *cla_addr, void **handle);
+void hifc_slq_free(void *dev, void *handle);
+u64 hifc_slq_get_addr(void *handle, u16 index);
+u64 hifc_slq_get_first_pageaddr(void *handle);
+
+typedef void (*comm_up_self_msg_proc)(void *handle, void *buf_in,
+ u16 in_size, void *buf_out,
+ u16 *out_size);
+void hifc_comm_recv_mgmt_self_cmd_reg(void *hwdev, u8 cmd,
+ comm_up_self_msg_proc proc);
+void hifc_comm_recv_up_self_cmd_unreg(void *hwdev, u8 cmd);
+
+/* defined by chip */
+enum hifc_fault_type {
+ FAULT_TYPE_CHIP,
+ FAULT_TYPE_UCODE,
+ FAULT_TYPE_MEM_RD_TIMEOUT,
+ FAULT_TYPE_MEM_WR_TIMEOUT,
+ FAULT_TYPE_REG_RD_TIMEOUT,
+ FAULT_TYPE_REG_WR_TIMEOUT,
+ FAULT_TYPE_PHY_FAULT,
+ FAULT_TYPE_MAX,
+};
+
+/* defined by chip */
+enum hifc_fault_err_level {
+ /* default err_level=FAULT_LEVEL_FATAL if
+ * type==FAULT_TYPE_MEM_RD_TIMEOUT || FAULT_TYPE_MEM_WR_TIMEOUT ||
+ * FAULT_TYPE_REG_RD_TIMEOUT || FAULT_TYPE_REG_WR_TIMEOUT ||
+ * FAULT_TYPE_UCODE
+ * other: err_level in event.chip.err_level if type==FAULT_TYPE_CHIP
+ */
+ FAULT_LEVEL_FATAL,
+ FAULT_LEVEL_SERIOUS_RESET,
+ FAULT_LEVEL_SERIOUS_FLR,
+ FAULT_LEVEL_GENERAL,
+ FAULT_LEVEL_SUGGESTION,
+ FAULT_LEVEL_MAX
+};
+
+enum hifc_fault_source_type {
+ /* same as FAULT_TYPE_CHIP */
+ HIFC_FAULT_SRC_HW_MGMT_CHIP = 0,
+ /* same as FAULT_TYPE_UCODE */
+ HIFC_FAULT_SRC_HW_MGMT_UCODE,
+ /* same as FAULT_TYPE_MEM_RD_TIMEOUT */
+ HIFC_FAULT_SRC_HW_MGMT_MEM_RD_TIMEOUT,
+ /* same as FAULT_TYPE_MEM_WR_TIMEOUT */
+ HIFC_FAULT_SRC_HW_MGMT_MEM_WR_TIMEOUT,
+ /* same as FAULT_TYPE_REG_RD_TIMEOUT */
+ HIFC_FAULT_SRC_HW_MGMT_REG_RD_TIMEOUT,
+ /* same as FAULT_TYPE_REG_WR_TIMEOUT */
+ HIFC_FAULT_SRC_HW_MGMT_REG_WR_TIMEOUT,
+ HIFC_FAULT_SRC_SW_MGMT_UCODE,
+ HIFC_FAULT_SRC_MGMT_WATCHDOG,
+ HIFC_FAULT_SRC_MGMT_RESET = 8,
+ HIFC_FAULT_SRC_HW_PHY_FAULT,
+ HIFC_FAULT_SRC_HOST_HEARTBEAT_LOST = 20,
+ HIFC_FAULT_SRC_TYPE_MAX,
+};
+
+struct hifc_fault_sw_mgmt {
+ u8 event_id;
+ u64 event_data;
+};
+
+union hifc_fault_hw_mgmt {
+ u32 val[4];
+ /* valid only type==FAULT_TYPE_CHIP */
+ struct {
+ u8 node_id;
+ /* enum hifc_fault_err_level */
+ u8 err_level;
+ u16 err_type;
+ u32 err_csr_addr;
+ u32 err_csr_value;
+ /* func_id valid only err_level==FAULT_LEVEL_SERIOUS_FLR
+ */
+ u16 func_id;
+ u16 rsvd2;
+ } chip;
+
+ /* valid only type==FAULT_TYPE_UCODE */
+ struct {
+ u8 cause_id;
+ u8 core_id;
+ u8 c_id;
+ u8 rsvd3;
+ u32 epc;
+ u32 rsvd4;
+ u32 rsvd5;
+ } ucode;
+
+ /* valid only type==FAULT_TYPE_MEM_RD_TIMEOUT ||
+ * FAULT_TYPE_MEM_WR_TIMEOUT
+ */
+ struct {
+ u32 err_csr_ctrl;
+ u32 err_csr_data;
+ u32 ctrl_tab;
+ u32 mem_index;
+ } mem_timeout;
+
+ /* valid only type==FAULT_TYPE_REG_RD_TIMEOUT ||
+ * FAULT_TYPE_REG_WR_TIMEOUT
+ */
+ struct {
+ u32 err_csr;
+ u32 rsvd6;
+ u32 rsvd7;
+ u32 rsvd8;
+ } reg_timeout;
+
+ struct {
+ /* 0: read; 1: write */
+ u8 op_type;
+ u8 port_id;
+ u8 dev_ad;
+ u8 rsvd9;
+ u32 csr_addr;
+ u32 op_data;
+ u32 rsvd10;
+ } phy_fault;
+};
+
+/* defined by chip */
+struct hifc_fault_event {
+ /* enum hifc_fault_type */
+ u8 type;
+ u8 rsvd0[3];
+ union hifc_fault_hw_mgmt event;
+};
+
+struct hifc_fault_recover_info {
+ u8 fault_src; /* enum hifc_fault_source_type */
+ u8 fault_lev; /* enum hifc_fault_err_level */
+ u8 rsvd0[2];
+ union {
+ union hifc_fault_hw_mgmt hw_mgmt;
+ struct hifc_fault_sw_mgmt sw_mgmt;
+ u32 mgmt_rsvd[4];
+ u32 host_rsvd[4];
+ } fault_data;
+};
+
+struct hifc_dcb_state {
+ u8 dcb_on;
+ u8 default_cos;
+ u8 up_cos[8];
+};
+
+enum link_err_type {
+ LINK_ERR_MODULE_UNRECOGENIZED,
+ LINK_ERR_NUM,
+};
+
+enum port_module_event_type {
+ HIFC_PORT_MODULE_CABLE_PLUGGED,
+ HIFC_PORT_MODULE_CABLE_UNPLUGGED,
+ HIFC_PORT_MODULE_LINK_ERR,
+ HIFC_PORT_MODULE_MAX_EVENT,
+};
+
+struct hifc_port_module_event {
+ enum port_module_event_type type;
+ enum link_err_type err_type;
+};
+
+struct hifc_event_link_info {
+ u8 valid;
+ u8 port_type;
+ u8 autoneg_cap;
+ u8 autoneg_state;
+ u8 duplex;
+ u8 speed;
+};
+
+struct hifc_mctp_host_info {
+ u8 major_cmd;
+ u8 sub_cmd;
+ u8 rsvd[2];
+
+ u32 data_len;
+ void *data;
+};
+
+enum hifc_event_type {
+ HIFC_EVENT_LINK_DOWN = 0,
+ HIFC_EVENT_LINK_UP = 1,
+ HIFC_EVENT_HEART_LOST = 2,
+ HIFC_EVENT_FAULT = 3,
+ HIFC_EVENT_NOTIFY_VF_DCB_STATE = 4,
+ HIFC_EVENT_DCB_STATE_CHANGE = 5,
+ HIFC_EVENT_FMW_ACT_NTC = 6,
+ HIFC_EVENT_PORT_MODULE_EVENT = 7,
+ HIFC_EVENT_MCTP_GET_HOST_INFO,
+ HIFC_EVENT_MULTI_HOST_MGMT,
+ HIFC_EVENT_INIT_MIGRATE_PF,
+};
+
+struct hifc_event_info {
+ enum hifc_event_type type;
+ union {
+ struct hifc_event_link_info link_info;
+ struct hifc_fault_event info;
+ struct hifc_dcb_state dcb_state;
+ struct hifc_port_module_event module_event;
+ u8 vf_default_cos;
+ struct hifc_mctp_host_info mctp_info;
+ };
+};
+
+enum hifc_ucode_event_type {
+ HIFC_INTERNAL_TSO_FATAL_ERROR = 0x0,
+ HIFC_INTERNAL_LRO_FATAL_ERROR = 0x1,
+ HIFC_INTERNAL_TX_FATAL_ERROR = 0x2,
+ HIFC_INTERNAL_RX_FATAL_ERROR = 0x3,
+ HIFC_INTERNAL_OTHER_FATAL_ERROR = 0x4,
+ HIFC_NIC_FATAL_ERROR_MAX = 0x8,
+};
+
+typedef void (*hifc_event_handler)(void *handle,
+ struct hifc_event_info *event);
+/* only register once */
+void hifc_event_register(void *dev, void *pri_handle,
+ hifc_event_handler callback);
+void hifc_event_unregister(void *dev);
+
+void hifc_detect_hw_present(void *hwdev);
+
+void hifc_set_chip_absent(void *hwdev);
+
+int hifc_get_chip_present_flag(void *hwdev);
+
+void hifc_set_pcie_order_cfg(void *handle);
+
+int hifc_get_mgmt_channel_status(void *handle);
+
+struct hifc_board_info {
+ u32 board_type;
+ u32 port_num;
+ u32 port_speed;
+ u32 pcie_width;
+ u32 host_num;
+ u32 pf_num;
+ u32 vf_total_num;
+ u32 tile_num;
+ u32 qcm_num;
+ u32 core_num;
+ u32 work_mode;
+ u32 service_mode;
+ u32 pcie_mode;
+ u32 cfg_addr;
+ u32 boot_sel;
+ u32 board_id;
+};
+
+int hifc_get_board_info(void *hwdev, struct hifc_board_info *info);
+
+int hifc_get_card_present_state(void *hwdev, bool *card_present_state);
+
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_hwdev.c b/drivers/scsi/huawei/hifc/hifc_hwdev.c
new file mode 100644
index 000000000000..760e02394b05
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_hwdev.c
@@ -0,0 +1,3675 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/semaphore.h>
+#include <linux/interrupt.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_eqs.h"
+#include "hifc_wq.h"
+#include "hifc_cmdq.h"
+#include "hifc_hwif.h"
+
+#define HIFC_DEAULT_EQ_MSIX_PENDING_LIMIT 0
+#define HIFC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF
+#define HIFC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG 7
+#define HIFC_FLR_TIMEOUT 1000
+#define HIFC_HT_GPA_PAGE_SIZE 4096UL
+#define HIFC_PPF_HT_GPA_SET_RETRY_TIMES 10
+#define HIFC_GET_SFP_INFO_REAL_TIME 0x1
+#define HIFC_GLB_SO_RO_CFG_SHIFT 0x0
+#define HIFC_GLB_SO_RO_CFG_MASK 0x1
+#define HIFC_DISABLE_ORDER 0
+#define HIFC_GLB_DMA_SO_RO_GET(val, member) \
+ (((val) >> HIFC_GLB_##member##_SHIFT) & HIFC_GLB_##member##_MASK)
+
+#define HIFC_GLB_DMA_SO_R0_CLEAR(val, member) \
+ ((val) & (~(HIFC_GLB_##member##_MASK << HIFC_GLB_##member##_SHIFT)))
+
+#define HIFC_GLB_DMA_SO_R0_SET(val, member) \
+ (((val) & HIFC_GLB_##member##_MASK) << HIFC_GLB_##member##_SHIFT)
+
+#define HIFC_MGMT_CHANNEL_STATUS_SHIFT 0x0
+#define HIFC_MGMT_CHANNEL_STATUS_MASK 0x1
+#define HIFC_ACTIVE_STATUS_MASK 0x80000000
+#define HIFC_ACTIVE_STATUS_CLEAR 0x7FFFFFFF
+
+#define HIFC_GET_MGMT_CHANNEL_STATUS(val, member) \
+ (((val) >> HIFC_##member##_SHIFT) & HIFC_##member##_MASK)
+
+#define HIFC_CLEAR_MGMT_CHANNEL_STATUS(val, member) \
+ ((val) & (~(HIFC_##member##_MASK << HIFC_##member##_SHIFT)))
+
+#define HIFC_SET_MGMT_CHANNEL_STATUS(val, member) \
+ (((val) & HIFC_##member##_MASK) << HIFC_##member##_SHIFT)
+
+#define HIFC_BOARD_IS_PHY(hwdev) \
+ ((hwdev)->board_info.board_type == 4 && \
+ (hwdev)->board_info.board_id == 24)
+
+struct comm_info_ht_gpa_set {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+ u32 rsvd1;
+ u32 rsvd2;
+ u64 page_pa0;
+ u64 page_pa1;
+};
+
+struct hifc_cons_idx_attr {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 dma_attr_off;
+ u8 pending_limit;
+ u8 coalescing_time;
+ u8 intr_en;
+ u16 intr_idx;
+ u32 l2nic_sqn;
+ u32 sq_id;
+ u64 ci_addr;
+};
+
+struct hifc_clear_doorbell {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 ppf_idx;
+ u8 rsvd1;
+};
+
+struct hifc_clear_resource {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 ppf_idx;
+ u8 rsvd1;
+};
+
+struct hifc_msix_config {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 msix_index;
+ u8 pending_cnt;
+ u8 coalesct_timer_cnt;
+ u8 lli_tmier_cnt;
+ u8 lli_credit_cnt;
+ u8 resend_timer_cnt;
+ u8 rsvd1[3];
+};
+
+enum func_tmr_bitmap_status {
+ FUNC_TMR_BITMAP_DISABLE,
+ FUNC_TMR_BITMAP_ENABLE,
+};
+
+struct hifc_func_tmr_bitmap_op {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 op_id; /* 0:start; 1:stop */
+ u8 ppf_idx;
+ u32 rsvd1;
+};
+
+struct hifc_ppf_tmr_op {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 ppf_idx;
+ u8 op_id; /* 0: stop timer; 1:start timer */
+ u8 rsvd1[2];
+ u32 rsvd2;
+};
+
+struct hifc_cmd_set_res_state {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 state;
+ u8 rsvd1;
+ u32 rsvd2;
+};
+
+int hifc_hw_rx_buf_size[] = {
+ HIFC_RX_BUF_SIZE_32B,
+ HIFC_RX_BUF_SIZE_64B,
+ HIFC_RX_BUF_SIZE_96B,
+ HIFC_RX_BUF_SIZE_128B,
+ HIFC_RX_BUF_SIZE_192B,
+ HIFC_RX_BUF_SIZE_256B,
+ HIFC_RX_BUF_SIZE_384B,
+ HIFC_RX_BUF_SIZE_512B,
+ HIFC_RX_BUF_SIZE_768B,
+ HIFC_RX_BUF_SIZE_1K,
+ HIFC_RX_BUF_SIZE_1_5K,
+ HIFC_RX_BUF_SIZE_2K,
+ HIFC_RX_BUF_SIZE_3K,
+ HIFC_RX_BUF_SIZE_4K,
+ HIFC_RX_BUF_SIZE_8K,
+ HIFC_RX_BUF_SIZE_16K,
+};
+
+struct hifc_comm_board_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ struct hifc_board_info info;
+
+ u32 rsvd1[4];
+};
+
+#define PHY_DOING_INIT_TIMEOUT (15 * 1000)
+
+struct hifc_phy_init_status {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 init_status;
+ u8 rsvd1[3];
+};
+
+enum phy_init_status_type {
+ PHY_INIT_DOING = 0,
+ PHY_INIT_SUCCESS = 1,
+ PHY_INIT_FAIL = 2,
+ PHY_NONSUPPORT = 3,
+};
+
+struct hifc_update_active {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u32 update_flag;
+ u32 update_status;
+};
+
+struct hifc_mgmt_watchdog_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u32 curr_time_h;
+ u32 curr_time_l;
+ u32 task_id;
+ u32 rsv;
+
+ u32 reg[13];
+ u32 pc;
+ u32 lr;
+ u32 cpsr;
+
+ u32 stack_top;
+ u32 stack_bottom;
+ u32 sp;
+ u32 curr_used;
+ u32 peak_used;
+ u32 is_overflow;
+
+ u32 stack_actlen;
+ u8 data[1024];
+};
+
+struct hifc_fmw_act_ntc {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u32 rsvd1[5];
+};
+
+#define HIFC_PAGE_SIZE_HW(pg_size) ((u8)ilog2((u32)((pg_size) >> 12)))
+
+struct hifc_wq_page_size {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 ppf_idx;
+ /* real_size=4KB*2^page_size, range(0~20) must be checked by driver */
+ u8 page_size;
+
+ u32 rsvd1;
+};
+
+#define MAX_PCIE_DFX_BUF_SIZE (1024)
+
+struct hifc_pcie_dfx_ntc {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ int len;
+ u32 rsvd;
+};
+
+struct hifc_pcie_dfx_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 host_id;
+ u8 last;
+ u8 rsvd[2];
+ u32 offset;
+
+ u8 data[MAX_PCIE_DFX_BUF_SIZE];
+};
+
+struct hifc_reg_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u32 reg_addr;
+ u32 val_length;
+
+ u32 data[2];
+};
+
+#define HIFC_DMA_ATTR_ENTRY_ST_SHIFT 0
+#define HIFC_DMA_ATTR_ENTRY_AT_SHIFT 8
+#define HIFC_DMA_ATTR_ENTRY_PH_SHIFT 10
+#define HIFC_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT 12
+#define HIFC_DMA_ATTR_ENTRY_TPH_EN_SHIFT 13
+
+#define HIFC_DMA_ATTR_ENTRY_ST_MASK 0xFF
+#define HIFC_DMA_ATTR_ENTRY_AT_MASK 0x3
+#define HIFC_DMA_ATTR_ENTRY_PH_MASK 0x3
+#define HIFC_DMA_ATTR_ENTRY_NO_SNOOPING_MASK 0x1
+#define HIFC_DMA_ATTR_ENTRY_TPH_EN_MASK 0x1
+
+#define HIFC_DMA_ATTR_ENTRY_SET(val, member) \
+ (((u32)(val) & HIFC_DMA_ATTR_ENTRY_##member##_MASK) << \
+ HIFC_DMA_ATTR_ENTRY_##member##_SHIFT)
+
+#define HIFC_DMA_ATTR_ENTRY_CLEAR(val, member) \
+ ((val) & (~(HIFC_DMA_ATTR_ENTRY_##member##_MASK \
+ << HIFC_DMA_ATTR_ENTRY_##member##_SHIFT)))
+
+#define HIFC_PCIE_ST_DISABLE 0
+#define HIFC_PCIE_AT_DISABLE 0
+#define HIFC_PCIE_PH_DISABLE 0
+
+#define PCIE_MSIX_ATTR_ENTRY 0
+
+#define HIFC_CHIP_PRESENT 1
+#define HIFC_CHIP_ABSENT 0
+
+struct hifc_cmd_fault_event {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ struct hifc_fault_event event;
+};
+
+#define HEARTBEAT_DRV_MAGIC_ACK 0x5A5A5A5A
+
+struct hifc_heartbeat_event {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 mgmt_init_state;
+ u8 rsvd1[3];
+ u32 heart; /* increased every event */
+ u32 drv_heart;
+};
+
+static void hifc_set_mgmt_channel_status(void *handle, bool state)
+{
+ struct hifc_hwdev *hwdev = handle;
+ u32 val;
+
+ if (!hwdev || hifc_func_type(hwdev) == TYPE_VF ||
+ !(hwdev->feature_cap & HIFC_FUNC_SUPP_DFX_REG))
+ return;
+
+ val = hifc_hwif_read_reg(hwdev->hwif, HIFC_ICPL_RESERVD_ADDR);
+ val = HIFC_CLEAR_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
+ val |= HIFC_SET_MGMT_CHANNEL_STATUS((u32)state, MGMT_CHANNEL_STATUS);
+
+ hifc_hwif_write_reg(hwdev->hwif, HIFC_ICPL_RESERVD_ADDR, val);
+}
+
+static void hifc_enable_mgmt_channel(void *hwdev, void *buf_out)
+{
+ struct hifc_hwdev *dev = hwdev;
+ struct hifc_update_active *active_info = buf_out;
+
+ if (!active_info || hifc_func_type(hwdev) == TYPE_VF ||
+ !(dev->feature_cap & HIFC_FUNC_SUPP_DFX_REG))
+ return;
+
+ if ((!active_info->status) &&
+ (active_info->update_status & HIFC_ACTIVE_STATUS_MASK)) {
+ active_info->update_status &= HIFC_ACTIVE_STATUS_CLEAR;
+ return;
+ }
+
+ hifc_set_mgmt_channel_status(hwdev, false);
+}
+
+int hifc_set_wq_page_size(struct hifc_hwdev *hwdev, u16 func_idx,
+ u32 page_size);
+
+#define HIFC_QUEUE_MIN_DEPTH 6
+#define HIFC_QUEUE_MAX_DEPTH 12
+#define HIFC_MAX_RX_BUFFER_SIZE 15
+
+#define ROOT_CTX_QPS_VALID(root_ctxt) \
+ ((root_ctxt)->rq_depth >= HIFC_QUEUE_MIN_DEPTH && \
+ (root_ctxt)->rq_depth <= HIFC_QUEUE_MAX_DEPTH && \
+ (root_ctxt)->sq_depth >= HIFC_QUEUE_MIN_DEPTH && \
+ (root_ctxt)->sq_depth <= HIFC_QUEUE_MAX_DEPTH && \
+ (root_ctxt)->rx_buf_sz <= HIFC_MAX_RX_BUFFER_SIZE)
+
+struct hifc_mgmt_status_log {
+ u8 status;
+ const char *log;
+};
+
+struct hifc_mgmt_status_log mgmt_status_log[] = {
+ {HIFC_MGMT_STATUS_ERR_PARAM, "Invalid parameter"},
+ {HIFC_MGMT_STATUS_ERR_FAILED, "Operation failed"},
+ {HIFC_MGMT_STATUS_ERR_PORT, "Invalid port"},
+ {HIFC_MGMT_STATUS_ERR_TIMEOUT, "Operation time out"},
+ {HIFC_MGMT_STATUS_ERR_NOMATCH, "Version not match"},
+ {HIFC_MGMT_STATUS_ERR_EXIST, "Entry exists"},
+ {HIFC_MGMT_STATUS_ERR_NOMEM, "Out of memory"},
+ {HIFC_MGMT_STATUS_ERR_INIT, "Feature not initialized"},
+ {HIFC_MGMT_STATUS_ERR_FAULT, "Invalid address"},
+ {HIFC_MGMT_STATUS_ERR_PERM, "Operation not permitted"},
+ {HIFC_MGMT_STATUS_ERR_EMPTY, "Table empty"},
+ {HIFC_MGMT_STATUS_ERR_FULL, "Table full"},
+ {HIFC_MGMT_STATUS_ERR_NOT_FOUND, "Not found"},
+ {HIFC_MGMT_STATUS_ERR_BUSY, "Device or resource busy "},
+ {HIFC_MGMT_STATUS_ERR_RESOURCE, "No resources for operation "},
+ {HIFC_MGMT_STATUS_ERR_CONFIG, "Invalid configuration"},
+ {HIFC_MGMT_STATUS_ERR_UNAVAIL, "Feature unavailable"},
+ {HIFC_MGMT_STATUS_ERR_CRC, "CRC check failed"},
+ {HIFC_MGMT_STATUS_ERR_NXIO, "No such device or address"},
+ {HIFC_MGMT_STATUS_ERR_ROLLBACK, "Chip rollback fail"},
+ {HIFC_MGMT_STATUS_ERR_LEN, "Length too short or too long"},
+ {HIFC_MGMT_STATUS_ERR_UNSUPPORT, "Feature not supported"},
+};
+
+static void __print_status_info(struct hifc_hwdev *dev,
+ enum hifc_mod_type mod, u8 cmd, int index)
+{
+ if (mod == HIFC_MOD_COMM) {
+ sdk_err(dev->dev_hdl, "Mgmt process mod(0x%x) cmd(0x%x) fail: %s",
+ mod, cmd, mgmt_status_log[index].log);
+ } else if (mod == HIFC_MOD_L2NIC ||
+ mod == HIFC_MOD_HILINK) {
+ sdk_err(dev->dev_hdl, "Mgmt process mod(0x%x) cmd(0x%x) fail: %s",
+ mod, cmd, mgmt_status_log[index].log);
+ }
+}
+
+static bool hifc_status_need_special_handle(enum hifc_mod_type mod,
+ u8 cmd, u8 status)
+{
+ if (mod == HIFC_MOD_L2NIC) {
+ /* optical module isn't plugged in */
+ if (((cmd == HIFC_PORT_CMD_GET_STD_SFP_INFO) ||
+ (cmd == HIFC_PORT_CMD_GET_SFP_INFO)) &&
+ (status == HIFC_MGMT_STATUS_ERR_NXIO))
+ return true;
+
+ if ((cmd == HIFC_PORT_CMD_SET_MAC ||
+ cmd == HIFC_PORT_CMD_UPDATE_MAC) &&
+ status == HIFC_MGMT_STATUS_ERR_EXIST)
+ return true;
+ }
+
+ return false;
+}
+
+static bool print_status_info_valid(enum hifc_mod_type mod,
+ const void *buf_out)
+{
+ if (!buf_out)
+ return false;
+
+ if (mod != HIFC_MOD_COMM && mod != HIFC_MOD_L2NIC &&
+ mod != HIFC_MOD_HILINK)
+ return false;
+
+ return true;
+}
+
+static void hifc_print_status_info(void *hwdev, enum hifc_mod_type mod,
+ u8 cmd, const void *buf_out)
+{
+ struct hifc_hwdev *dev = hwdev;
+ int i, size;
+ u8 status;
+
+ if (!print_status_info_valid(mod, buf_out))
+ return;
+
+ status = *(u8 *)buf_out;
+
+ if (!status)
+ return;
+
+ if (hifc_status_need_special_handle(mod, cmd, status))
+ return;
+
+ size = sizeof(mgmt_status_log) / sizeof(mgmt_status_log[0]);
+ for (i = 0; i < size; i++) {
+ if (status == mgmt_status_log[i].status) {
+ __print_status_info(dev, mod, cmd, i);
+ return;
+ }
+ }
+
+ if (mod == HIFC_MOD_COMM) {
+ sdk_err(dev->dev_hdl, "Mgmt process mod(0x%x) cmd(0x%x) return driver unknown status(0x%x)\n",
+ mod, cmd, status);
+ } else if (mod == HIFC_MOD_L2NIC || mod == HIFC_MOD_HILINK) {
+ sdk_err(dev->dev_hdl, "Mgmt process mod(0x%x) cmd(0x%x) return driver unknown status(0x%x)\n",
+ mod, cmd, status);
+ }
+}
+
+void hifc_set_chip_present(void *hwdev)
+{
+ ((struct hifc_hwdev *)hwdev)->chip_present_flag = HIFC_CHIP_PRESENT;
+}
+
+void hifc_set_chip_absent(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ sdk_err(dev->dev_hdl, "Card not present\n");
+ dev->chip_present_flag = HIFC_CHIP_ABSENT;
+}
+
+int hifc_get_chip_present_flag(void *hwdev)
+{
+ int flag;
+
+ if (!hwdev)
+ return -EINVAL;
+ flag = ((struct hifc_hwdev *)hwdev)->chip_present_flag;
+ return flag;
+}
+
+void hifc_force_complete_all(void *hwdev)
+{
+ struct hifc_hwdev *dev = (struct hifc_hwdev *)hwdev;
+ struct hifc_recv_msg *recv_resp_msg;
+
+ set_bit(HIFC_HWDEV_STATE_BUSY, &dev->func_state);
+
+ if (hifc_func_type(dev) != TYPE_VF &&
+ hifc_is_hwdev_mod_inited(dev, HIFC_HWDEV_MGMT_INITED)) {
+ recv_resp_msg = &dev->pf_to_mgmt->recv_resp_msg_from_mgmt;
+ if (dev->pf_to_mgmt->event_flag == SEND_EVENT_START) {
+ complete(&recv_resp_msg->recv_done);
+ dev->pf_to_mgmt->event_flag = SEND_EVENT_TIMEOUT;
+ }
+ }
+
+ /* only flush sync cmdq to avoid blocking remove */
+ if (hifc_is_hwdev_mod_inited(dev, HIFC_HWDEV_CMDQ_INITED))
+ hifc_cmdq_flush_cmd(hwdev,
+ &dev->cmdqs->cmdq[HIFC_CMDQ_SYNC]);
+
+ clear_bit(HIFC_HWDEV_STATE_BUSY, &dev->func_state);
+}
+
+void hifc_detect_hw_present(void *hwdev)
+{
+ u32 addr, attr1;
+
+ addr = HIFC_CSR_FUNC_ATTR1_ADDR;
+ attr1 = hifc_hwif_read_reg(((struct hifc_hwdev *)hwdev)->hwif, addr);
+ if (attr1 == HIFC_PCIE_LINK_DOWN) {
+ hifc_set_chip_absent(hwdev);
+ hifc_force_complete_all(hwdev);
+ }
+}
+
+void hifc_record_pcie_error(void *hwdev)
+{
+ struct hifc_hwdev *dev = (struct hifc_hwdev *)hwdev;
+
+ if (!hwdev)
+ return;
+
+ atomic_inc(&dev->hw_stats.fault_event_stats.pcie_fault_stats);
+}
+
+static inline void __set_heartbeat_ehd_detect_delay(struct hifc_hwdev *hwdev,
+ u32 delay_ms)
+{
+ hwdev->heartbeat_ehd.start_detect_jiffies =
+ jiffies + msecs_to_jiffies(delay_ms);
+}
+
+static int __pf_to_mgmt_pre_handle(struct hifc_hwdev *hwdev,
+ enum hifc_mod_type mod, u8 cmd)
+{
+ if (hifc_get_mgmt_channel_status(hwdev)) {
+ if (mod == HIFC_MOD_COMM || mod == HIFC_MOD_L2NIC)
+ return HIFC_DEV_BUSY_ACTIVE_FW;
+ else
+ return -EBUSY;
+ }
+
+ /* Set channel invalid, don't allowed to send other cmd */
+ if (mod == HIFC_MOD_COMM && cmd == HIFC_MGMT_CMD_ACTIVATE_FW) {
+ hifc_set_mgmt_channel_status(hwdev, true);
+ /* stop heartbeat enhanced detection temporary, and will
+ * restart in firmware active event when mgmt is resetted
+ */
+ __set_heartbeat_ehd_detect_delay(hwdev,
+ HIFC_DEV_ACTIVE_FW_TIMEOUT);
+ }
+
+ return 0;
+}
+
+static void __pf_to_mgmt_after_handle(struct hifc_hwdev *hwdev,
+ enum hifc_mod_type mod, u8 cmd,
+ int sw_status, void *mgmt_status)
+{
+ /* if activate fw is failed, set channel valid */
+ if (mod == HIFC_MOD_COMM &&
+ cmd == HIFC_MGMT_CMD_ACTIVATE_FW) {
+ if (sw_status)
+ hifc_set_mgmt_channel_status(hwdev, false);
+ else
+ hifc_enable_mgmt_channel(hwdev, mgmt_status);
+ }
+}
+
+int hifc_pf_msg_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size, u32 timeout)
+{
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (!((struct hifc_hwdev *)hwdev)->chip_present_flag)
+ return -EPERM;
+
+ if (!hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED))
+ return -EPERM;
+
+ if (in_size > HIFC_MSG_TO_MGMT_MAX_LEN)
+ return -EINVAL;
+
+ err = __pf_to_mgmt_pre_handle(hwdev, mod, cmd);
+ if (err)
+ return err;
+
+ err = hifc_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size,
+ buf_out, out_size, timeout);
+ __pf_to_mgmt_after_handle(hwdev, mod, cmd, err, buf_out);
+
+ return err;
+}
+
+static bool is_sfp_info_cmd_cached(struct hifc_hwdev *hwdev,
+ enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_cmd_get_sfp_qsfp_info *sfp_info;
+ struct hifc_port_routine_cmd *rt_cmd;
+ struct card_node *chip_node = hwdev->chip_node;
+
+ sfp_info = buf_in;
+ if (!chip_node->rt_cmd || sfp_info->port_id >= HIFC_MAX_PORT_ID ||
+ *out_size < sizeof(*sfp_info))
+ return false;
+
+ if (sfp_info->version == HIFC_GET_SFP_INFO_REAL_TIME)
+ return false;
+
+ rt_cmd = &chip_node->rt_cmd[sfp_info->port_id];
+ mutex_lock(&chip_node->sfp_mutex);
+ memcpy(buf_out, &rt_cmd->sfp_info, sizeof(*sfp_info));
+ mutex_unlock(&chip_node->sfp_mutex);
+
+ return true;
+}
+
+static bool is_sfp_abs_cmd_cached(struct hifc_hwdev *hwdev,
+ enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_cmd_get_light_module_abs *abs;
+ struct hifc_port_routine_cmd *rt_cmd;
+ struct card_node *chip_node = hwdev->chip_node;
+
+ abs = buf_in;
+ if (!chip_node->rt_cmd || abs->port_id >= HIFC_MAX_PORT_ID ||
+ *out_size < sizeof(*abs))
+ return false;
+
+ if (abs->version == HIFC_GET_SFP_INFO_REAL_TIME)
+ return false;
+
+ rt_cmd = &chip_node->rt_cmd[abs->port_id];
+ mutex_lock(&chip_node->sfp_mutex);
+ memcpy(buf_out, &rt_cmd->abs, sizeof(*abs));
+ mutex_unlock(&chip_node->sfp_mutex);
+
+ return true;
+}
+
+static bool driver_processed_cmd(struct hifc_hwdev *hwdev,
+ enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct card_node *chip_node = hwdev->chip_node;
+
+ if (mod == HIFC_MOD_L2NIC) {
+ if (cmd == HIFC_PORT_CMD_GET_SFP_INFO &&
+ chip_node->rt_cmd->up_send_sfp_info) {
+ return is_sfp_info_cmd_cached(hwdev, mod, cmd, buf_in,
+ in_size, buf_out,
+ out_size);
+ } else if (cmd == HIFC_PORT_CMD_GET_SFP_ABS &&
+ chip_node->rt_cmd->up_send_sfp_abs) {
+ return is_sfp_abs_cmd_cached(hwdev, mod, cmd, buf_in,
+ in_size, buf_out,
+ out_size);
+ }
+ }
+
+ return false;
+}
+
+static int send_sync_mgmt_msg(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size, u32 timeout)
+{
+ unsigned long end;
+
+ end = jiffies + msecs_to_jiffies(HIFC_DEV_ACTIVE_FW_TIMEOUT);
+ do {
+ if (!hifc_get_mgmt_channel_status(hwdev) ||
+ !hifc_get_chip_present_flag(hwdev))
+ break;
+
+ msleep(1000);
+ } while (time_before(jiffies, end));
+
+ if (driver_processed_cmd(hwdev, mod, cmd, buf_in, in_size, buf_out,
+ out_size))
+ return 0;
+
+ return hifc_pf_msg_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size,
+ buf_out, out_size, timeout);
+}
+
+int hifc_msg_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size, u32 timeout)
+{
+ struct hifc_hwdev *dev = hwdev;
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (!(dev->chip_present_flag))
+ return -EPERM;
+
+ err = send_sync_mgmt_msg(hwdev, mod, cmd, buf_in, in_size,
+ buf_out, out_size, timeout);
+
+ hifc_print_status_info(hwdev, mod, cmd, buf_out);
+
+ return err;
+}
+
+/* PF/VF send msg to uP by api cmd, and return immediately */
+int hifc_msg_to_mgmt_async(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size)
+{
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag) ||
+ !hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED) ||
+ hifc_get_mgmt_channel_status(hwdev))
+ return -EPERM;
+
+ if (hifc_func_type(hwdev) == TYPE_VF) {
+ err = -EFAULT;
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Mailbox don't support async cmd\n");
+ } else {
+ err = hifc_pf_to_mgmt_async(hwdev, mod, cmd, buf_in, in_size);
+ }
+
+ return err;
+}
+
+int hifc_msg_to_mgmt_no_ack(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size)
+{
+ struct hifc_hwdev *dev = hwdev;
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (!(dev->chip_present_flag))
+ return -EPERM;
+
+ err = hifc_pf_to_mgmt_no_ack(hwdev, mod, cmd, buf_in, in_size);
+
+ return err;
+}
+
+/**
+ * hifc_cpu_to_be32 - convert data to big endian 32 bit format
+ * @data: the data to convert
+ * @len: length of data to convert, must be Multiple of 4B
+ **/
+void hifc_cpu_to_be32(void *data, int len)
+{
+ int i, chunk_sz = sizeof(u32);
+ u32 *mem = data;
+
+ if (!data)
+ return;
+
+ len = len / chunk_sz;
+
+ for (i = 0; i < len; i++) {
+ *mem = cpu_to_be32(*mem);
+ mem++;
+ }
+}
+
+/**
+ * hifc_cpu_to_be32 - convert data from big endian 32 bit format
+ * @data: the data to convert
+ * @len: length of data to convert
+ **/
+void hifc_be32_to_cpu(void *data, int len)
+{
+ int i, chunk_sz = sizeof(u32);
+ u32 *mem = data;
+
+ if (!data)
+ return;
+
+ len = len / chunk_sz;
+
+ for (i = 0; i < len; i++) {
+ *mem = be32_to_cpu(*mem);
+ mem++;
+ }
+}
+
+/**
+ * hifc_set_sge - set dma area in scatter gather entry
+ * @sge: scatter gather entry
+ * @addr: dma address
+ * @len: length of relevant data in the dma address
+ **/
+void hifc_set_sge(struct hifc_sge *sge, dma_addr_t addr, u32 len)
+{
+ sge->hi_addr = upper_32_bits(addr);
+ sge->lo_addr = lower_32_bits(addr);
+ sge->len = len;
+}
+
+int hifc_set_ci_table(void *hwdev, u16 q_id, struct hifc_sq_attr *attr)
+{
+ struct hifc_cons_idx_attr cons_idx_attr = {0};
+ u16 out_size = sizeof(cons_idx_attr);
+ int err;
+
+ if (!hwdev || !attr)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &cons_idx_attr.func_idx);
+ if (err)
+ return err;
+
+ cons_idx_attr.dma_attr_off = attr->dma_attr_off;
+ cons_idx_attr.pending_limit = attr->pending_limit;
+ cons_idx_attr.coalescing_time = attr->coalescing_time;
+
+ if (attr->intr_en) {
+ cons_idx_attr.intr_en = attr->intr_en;
+ cons_idx_attr.intr_idx = attr->intr_idx;
+ }
+
+ cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
+ cons_idx_attr.sq_id = q_id;
+
+ cons_idx_attr.ci_addr = attr->ci_dma_base;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_L2NIC_SQ_CI_ATTR_SET,
+ &cons_idx_attr, sizeof(cons_idx_attr),
+ &cons_idx_attr, &out_size, 0);
+ if (err || !out_size || cons_idx_attr.status) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to set ci attribute table, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, cons_idx_attr.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int hifc_set_cmdq_depth(struct hifc_hwdev *hwdev, u16 cmdq_depth)
+{
+ struct hifc_root_ctxt root_ctxt = {0};
+ u16 out_size = sizeof(root_ctxt);
+ int err;
+
+ err = hifc_global_func_id_get(hwdev, &root_ctxt.func_idx);
+ if (err)
+ return err;
+
+ root_ctxt.ppf_idx = hifc_ppf_idx(hwdev);
+
+ root_ctxt.set_cmdq_depth = 1;
+ root_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth);
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_VAT_SET,
+ &root_ctxt, sizeof(root_ctxt),
+ &root_ctxt, &out_size, 0);
+ if (err || !out_size || root_ctxt.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to set cmdq depth, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, root_ctxt.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static u16 get_hw_rx_buf_size(int rx_buf_sz)
+{
+#define DEFAULT_RX_BUF_SIZE ((u16)0xB)
+ u16 num_hw_types =
+ sizeof(hifc_hw_rx_buf_size) /
+ sizeof(hifc_hw_rx_buf_size[0]);
+ u16 i;
+
+ for (i = 0; i < num_hw_types; i++) {
+ if (hifc_hw_rx_buf_size[i] == rx_buf_sz)
+ return i;
+ }
+
+ pr_err("Chip can't support rx buf size of %d\n", rx_buf_sz);
+
+ return DEFAULT_RX_BUF_SIZE;
+}
+
+int hifc_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz)
+{
+ struct hifc_root_ctxt root_ctxt = {0};
+ u16 out_size = sizeof(root_ctxt);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &root_ctxt.func_idx);
+ if (err)
+ return err;
+
+ root_ctxt.ppf_idx = hifc_ppf_idx(hwdev);
+
+ root_ctxt.set_cmdq_depth = 0;
+ root_ctxt.cmdq_depth = 0;
+
+ root_ctxt.lro_en = 1;
+
+ root_ctxt.rq_depth = (u16)ilog2(rq_depth);
+ root_ctxt.rx_buf_sz = get_hw_rx_buf_size(rx_buf_sz);
+ root_ctxt.sq_depth = (u16)ilog2(sq_depth);
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_VAT_SET,
+ &root_ctxt, sizeof(root_ctxt),
+ &root_ctxt, &out_size, 0);
+ if (err || !out_size || root_ctxt.status) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to set root context, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, root_ctxt.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int hifc_clean_root_ctxt(void *hwdev)
+{
+ struct hifc_root_ctxt root_ctxt = {0};
+ u16 out_size = sizeof(root_ctxt);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &root_ctxt.func_idx);
+ if (err)
+ return err;
+
+ root_ctxt.ppf_idx = hifc_ppf_idx(hwdev);
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_VAT_SET,
+ &root_ctxt, sizeof(root_ctxt),
+ &root_ctxt, &out_size, 0);
+ if (err || !out_size || root_ctxt.status) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to set root context, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, root_ctxt.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int wait_for_flr_finish(struct hifc_hwif *hwif)
+{
+ u32 cnt = 0;
+ enum hifc_pf_status status;
+
+ while (cnt < HIFC_FLR_TIMEOUT) {
+ status = hifc_get_pf_status(hwif);
+ if (status == HIFC_PF_STATUS_FLR_FINISH_FLAG) {
+ hifc_set_pf_status(hwif, HIFC_PF_STATUS_ACTIVE_FLAG);
+ return 0;
+ }
+
+ usleep_range(9900, 10000);
+ cnt++;
+ }
+
+ return -EFAULT;
+}
+
+#define HIFC_WAIT_CMDQ_IDLE_TIMEOUT 5000
+
+static int wait_cmdq_stop(struct hifc_hwdev *hwdev)
+{
+ enum hifc_cmdq_type cmdq_type;
+ struct hifc_cmdqs *cmdqs = hwdev->cmdqs;
+ u32 cnt = 0;
+ int err = 0;
+
+ if (!(cmdqs->status & HIFC_CMDQ_ENABLE))
+ return 0;
+
+ cmdqs->status &= ~HIFC_CMDQ_ENABLE;
+
+ while (cnt < HIFC_WAIT_CMDQ_IDLE_TIMEOUT && hwdev->chip_present_flag) {
+ err = 0;
+ cmdq_type = HIFC_CMDQ_SYNC;
+ for (; cmdq_type < HIFC_MAX_CMDQ_TYPES; cmdq_type++) {
+ if (!hifc_cmdq_idle(&cmdqs->cmdq[cmdq_type])) {
+ err = -EBUSY;
+ break;
+ }
+ }
+
+ if (!err)
+ return 0;
+
+ usleep_range(500, 1000);
+ cnt++;
+ }
+
+ cmdq_type = HIFC_CMDQ_SYNC;
+ for (; cmdq_type < HIFC_MAX_CMDQ_TYPES; cmdq_type++) {
+ if (!hifc_cmdq_idle(&cmdqs->cmdq[cmdq_type]))
+ sdk_err(hwdev->dev_hdl, "Cmdq %d busy\n", cmdq_type);
+ }
+
+ cmdqs->status |= HIFC_CMDQ_ENABLE;
+
+ return err;
+}
+
+static int hifc_pf_rx_tx_flush(struct hifc_hwdev *hwdev)
+{
+ struct hifc_hwif *hwif = hwdev->hwif;
+ struct hifc_clear_doorbell clear_db = {0};
+ struct hifc_clear_resource clr_res = {0};
+ u16 out_size, func_id;
+ int err;
+ int ret = 0;
+
+ /* wait ucode stop I/O */
+ msleep(100);
+
+ err = wait_cmdq_stop(hwdev);
+ if (err) {
+ sdk_warn(hwdev->dev_hdl, "CMDQ is still working, please check CMDQ timeout value is reasonable\n");
+ ret = err;
+ }
+
+ hifc_disable_doorbell(hwif);
+
+ out_size = sizeof(clear_db);
+ func_id = hifc_global_func_id_hw(hwdev);
+ clear_db.func_idx = func_id;
+ clear_db.ppf_idx = HIFC_HWIF_PPF_IDX(hwif);
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_FLUSH_DOORBELL, &clear_db,
+ sizeof(clear_db), &clear_db, &out_size, 0);
+ if (err || !out_size || clear_db.status) {
+ sdk_warn(hwdev->dev_hdl, "Failed to flush doorbell, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, clear_db.status, out_size);
+ if (err)
+ ret = err;
+ else
+ ret = -EFAULT;
+ }
+
+ hifc_set_pf_status(hwif, HIFC_PF_STATUS_FLR_START_FLAG);
+
+ clr_res.func_idx = func_id;
+ clr_res.ppf_idx = HIFC_HWIF_PPF_IDX(hwif);
+
+ err = hifc_msg_to_mgmt_no_ack(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_START_FLR, &clr_res,
+ sizeof(clr_res));
+ if (err) {
+ sdk_warn(hwdev->dev_hdl, "Failed to notice flush message\n");
+ ret = err;
+ }
+
+ err = wait_for_flr_finish(hwif);
+ if (err) {
+ sdk_warn(hwdev->dev_hdl, "Wait firmware FLR timeout\n");
+ ret = err;
+ }
+
+ hifc_enable_doorbell(hwif);
+
+ err = hifc_reinit_cmdq_ctxts(hwdev);
+ if (err) {
+ sdk_warn(hwdev->dev_hdl, "Failed to reinit cmdq\n");
+ ret = err;
+ }
+
+ return ret;
+}
+
+int hifc_func_rx_tx_flush(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (!dev->chip_present_flag)
+ return 0;
+
+ return hifc_pf_rx_tx_flush(dev);
+}
+
+int hifc_get_interrupt_cfg(void *hwdev,
+ struct nic_interrupt_info *interrupt_info)
+{
+ struct hifc_hwdev *nic_hwdev = hwdev;
+ struct hifc_msix_config msix_cfg = {0};
+ u16 out_size = sizeof(msix_cfg);
+ int err;
+
+ if (!hwdev || !interrupt_info)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &msix_cfg.func_id);
+ if (err)
+ return err;
+
+ msix_cfg.msix_index = interrupt_info->msix_index;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_MSI_CTRL_REG_RD_BY_UP,
+ &msix_cfg, sizeof(msix_cfg),
+ &msix_cfg, &out_size, 0);
+ if (err || !out_size || msix_cfg.status) {
+ sdk_err(nic_hwdev->dev_hdl, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, msix_cfg.status, out_size);
+ return -EINVAL;
+ }
+
+ interrupt_info->lli_credit_limit = msix_cfg.lli_credit_cnt;
+ interrupt_info->lli_timer_cfg = msix_cfg.lli_tmier_cnt;
+ interrupt_info->pending_limt = msix_cfg.pending_cnt;
+ interrupt_info->coalesc_timer_cfg = msix_cfg.coalesct_timer_cnt;
+ interrupt_info->resend_timer_cfg = msix_cfg.resend_timer_cnt;
+
+ return 0;
+}
+
+int hifc_set_interrupt_cfg(void *hwdev,
+ struct nic_interrupt_info interrupt_info)
+{
+ struct hifc_hwdev *nic_hwdev = hwdev;
+ struct hifc_msix_config msix_cfg = {0};
+ struct nic_interrupt_info temp_info;
+ u16 out_size = sizeof(msix_cfg);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ temp_info.msix_index = interrupt_info.msix_index;
+
+ err = hifc_get_interrupt_cfg(hwdev, &temp_info);
+ if (err)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &msix_cfg.func_id);
+ if (err)
+ return err;
+
+ msix_cfg.msix_index = (u16)interrupt_info.msix_index;
+ msix_cfg.lli_credit_cnt = temp_info.lli_credit_limit;
+ msix_cfg.lli_tmier_cnt = temp_info.lli_timer_cfg;
+ msix_cfg.pending_cnt = temp_info.pending_limt;
+ msix_cfg.coalesct_timer_cnt = temp_info.coalesc_timer_cfg;
+ msix_cfg.resend_timer_cnt = temp_info.resend_timer_cfg;
+
+ if (interrupt_info.lli_set) {
+ msix_cfg.lli_credit_cnt = interrupt_info.lli_credit_limit;
+ msix_cfg.lli_tmier_cnt = interrupt_info.lli_timer_cfg;
+ }
+
+ if (interrupt_info.interrupt_coalesc_set) {
+ msix_cfg.pending_cnt = interrupt_info.pending_limt;
+ msix_cfg.coalesct_timer_cnt = interrupt_info.coalesc_timer_cfg;
+ msix_cfg.resend_timer_cnt = interrupt_info.resend_timer_cfg;
+ }
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_MSI_CTRL_REG_WR_BY_UP,
+ &msix_cfg, sizeof(msix_cfg),
+ &msix_cfg, &out_size, 0);
+ if (err || !out_size || msix_cfg.status) {
+ sdk_err(nic_hwdev->dev_hdl, "Failed to set interrupt config, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, msix_cfg.status, out_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define HIFC_MSIX_CNT_RESEND_TIMER_SHIFT 29
+#define HIFC_MSIX_CNT_RESEND_TIMER_MASK 0x7U
+
+#define HIFC_MSIX_CNT_SET(val, member) \
+ (((val) & HIFC_MSIX_CNT_##member##_MASK) << \
+ HIFC_MSIX_CNT_##member##_SHIFT)
+
+void hifc_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx,
+ u8 clear_resend_en)
+{
+ struct hifc_hwif *hwif;
+ u32 msix_ctrl = 0, addr;
+
+ if (!hwdev)
+ return;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ msix_ctrl = HIFC_MSIX_CNT_SET(clear_resend_en, RESEND_TIMER);
+
+ addr = HIFC_CSR_MSIX_CNT_ADDR(msix_idx);
+
+ hifc_hwif_write_reg(hwif, addr, msix_ctrl);
+}
+
+static int init_aeqs_msix_attr(struct hifc_hwdev *hwdev)
+{
+ struct hifc_aeqs *aeqs = hwdev->aeqs;
+ struct nic_interrupt_info info = {0};
+ struct hifc_eq *eq;
+ u16 q_id;
+ int err;
+
+ info.lli_set = 0;
+ info.interrupt_coalesc_set = 1;
+ info.pending_limt = HIFC_DEAULT_EQ_MSIX_PENDING_LIMIT;
+ info.coalesc_timer_cfg = HIFC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG;
+ info.resend_timer_cfg = HIFC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
+
+ for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) {
+ eq = &aeqs->aeq[q_id];
+ info.msix_index = eq->eq_irq.msix_entry_idx;
+ err = hifc_set_interrupt_cfg(hwdev, info);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Set msix attr for aeq %d failed\n",
+ q_id);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+static int init_ceqs_msix_attr(struct hifc_hwdev *hwdev)
+{
+ struct hifc_ceqs *ceqs = hwdev->ceqs;
+ struct nic_interrupt_info info = {0};
+ struct hifc_eq *eq;
+ u16 q_id;
+ int err;
+
+ info.lli_set = 0;
+ info.interrupt_coalesc_set = 1;
+ info.pending_limt = HIFC_DEAULT_EQ_MSIX_PENDING_LIMIT;
+ info.coalesc_timer_cfg = HIFC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG;
+ info.resend_timer_cfg = HIFC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
+
+ for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) {
+ eq = &ceqs->ceq[q_id];
+ info.msix_index = eq->eq_irq.msix_entry_idx;
+ err = hifc_set_interrupt_cfg(hwdev, info);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Set msix attr for ceq %d failed\n",
+ q_id);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * set_pf_dma_attr_entry - set the dma attributes for entry
+ * @hwdev: the pointer to hw device
+ * @entry_idx: the entry index in the dma table
+ * @st: PCIE TLP steering tag
+ * @at: PCIE TLP AT field
+ * @ph: PCIE TLP Processing Hint field
+ * @no_snooping: PCIE TLP No snooping
+ * @tph_en: PCIE TLP Processing Hint Enable
+ **/
+static void set_pf_dma_attr_entry(struct hifc_hwdev *hwdev, u32 entry_idx,
+ u8 st, u8 at, u8 ph,
+ enum hifc_pcie_nosnoop no_snooping,
+ enum hifc_pcie_tph tph_en)
+{
+ u32 addr, val, dma_attr_entry;
+
+ /* Read Modify Write */
+ addr = HIFC_CSR_DMA_ATTR_TBL_ADDR(entry_idx);
+
+ val = hifc_hwif_read_reg(hwdev->hwif, addr);
+ val = HIFC_DMA_ATTR_ENTRY_CLEAR(val, ST) &
+ HIFC_DMA_ATTR_ENTRY_CLEAR(val, AT) &
+ HIFC_DMA_ATTR_ENTRY_CLEAR(val, PH) &
+ HIFC_DMA_ATTR_ENTRY_CLEAR(val, NO_SNOOPING) &
+ HIFC_DMA_ATTR_ENTRY_CLEAR(val, TPH_EN);
+
+ dma_attr_entry = HIFC_DMA_ATTR_ENTRY_SET(st, ST) |
+ HIFC_DMA_ATTR_ENTRY_SET(at, AT) |
+ HIFC_DMA_ATTR_ENTRY_SET(ph, PH) |
+ HIFC_DMA_ATTR_ENTRY_SET(no_snooping, NO_SNOOPING) |
+ HIFC_DMA_ATTR_ENTRY_SET(tph_en, TPH_EN);
+
+ val |= dma_attr_entry;
+ hifc_hwif_write_reg(hwdev->hwif, addr, val);
+}
+
+/**
+ * dma_attr_table_init - initialize the the default dma attributes
+ * @hwdev: the pointer to hw device
+ * Return: 0 - success, negative - failure
+ **/
+static int dma_attr_table_init(struct hifc_hwdev *hwdev)
+{
+ int err = 0;
+
+ set_pf_dma_attr_entry(hwdev, PCIE_MSIX_ATTR_ENTRY,
+ HIFC_PCIE_ST_DISABLE,
+ HIFC_PCIE_AT_DISABLE,
+ HIFC_PCIE_PH_DISABLE,
+ HIFC_PCIE_SNOOP,
+ HIFC_PCIE_TPH_DISABLE);
+
+ return err;
+}
+
+static int resources_state_set(struct hifc_hwdev *hwdev,
+ enum hifc_res_state state)
+{
+ struct hifc_cmd_set_res_state res_state = {0};
+ u16 out_size = sizeof(res_state);
+ int err;
+
+ err = hifc_global_func_id_get(hwdev, &res_state.func_idx);
+ if (err)
+ return err;
+
+ res_state.state = state;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_RES_STATE_SET,
+ &res_state, sizeof(res_state),
+ &res_state, &out_size, 0);
+ if (err || !out_size || res_state.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to set resources state, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, res_state.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void comm_mgmt_msg_handler(void *hwdev, void *pri_handle, u8 cmd,
+ void *buf_in, u16 in_size, void *buf_out,
+ u16 *out_size)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt = pri_handle;
+ u8 cmd_idx;
+ u32 *mem;
+ u16 i;
+
+ for (cmd_idx = 0; cmd_idx < pf_to_mgmt->proc.cmd_num; cmd_idx++) {
+ if (cmd == pf_to_mgmt->proc.info[cmd_idx].cmd) {
+ if (!pf_to_mgmt->proc.info[cmd_idx].proc) {
+ sdk_warn(pf_to_mgmt->hwdev->dev_hdl,
+ "PF recv up comm msg handle null, cmd(0x%x)\n",
+ cmd);
+ } else {
+ pf_to_mgmt->proc.info[cmd_idx].proc(hwdev,
+ buf_in, in_size, buf_out, out_size);
+ }
+
+ return;
+ }
+ }
+
+ sdk_warn(pf_to_mgmt->hwdev->dev_hdl, "Received mgmt cpu event: 0x%x\n",
+ cmd);
+
+ mem = buf_in;
+ for (i = 0; i < (in_size / sizeof(u32)); i++) {
+ pr_info("0x%x\n", *mem);
+ mem++;
+ }
+
+ *out_size = 0;
+}
+
+static int hifc_comm_aeqs_init(struct hifc_hwdev *hwdev)
+{
+ struct irq_info aeq_irqs[HIFC_MAX_AEQS] = {{0} };
+ u16 num_aeqs, resp_num_irq = 0, i;
+ int err;
+
+ num_aeqs = HIFC_HWIF_NUM_AEQS(hwdev->hwif);
+ if (num_aeqs > HIFC_MAX_AEQS) {
+ sdk_warn(hwdev->dev_hdl, "Adjust aeq num to %d\n",
+ HIFC_MAX_AEQS);
+ num_aeqs = HIFC_MAX_AEQS;
+ }
+ err = hifc_alloc_irqs(hwdev, SERVICE_T_INTF, num_aeqs, aeq_irqs,
+ &resp_num_irq);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to alloc aeq irqs, num_aeqs: %d\n",
+ num_aeqs);
+ return err;
+ }
+
+ if (resp_num_irq < num_aeqs) {
+ sdk_warn(hwdev->dev_hdl, "Adjust aeq num to %d\n",
+ resp_num_irq);
+ num_aeqs = resp_num_irq;
+ }
+
+ err = hifc_aeqs_init(hwdev, num_aeqs, aeq_irqs);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init aeqs\n");
+ goto aeqs_init_err;
+ }
+
+ set_bit(HIFC_HWDEV_AEQ_INITED, &hwdev->func_state);
+
+ return 0;
+
+aeqs_init_err:
+ for (i = 0; i < num_aeqs; i++)
+ hifc_free_irq(hwdev, SERVICE_T_INTF, aeq_irqs[i].irq_id);
+
+ return err;
+}
+
+static void hifc_comm_aeqs_free(struct hifc_hwdev *hwdev)
+{
+ struct irq_info aeq_irqs[HIFC_MAX_AEQS] = {{0} };
+ u16 num_irqs, i;
+
+ clear_bit(HIFC_HWDEV_AEQ_INITED, &hwdev->func_state);
+
+ hifc_get_aeq_irqs(hwdev, aeq_irqs, &num_irqs);
+ hifc_aeqs_free(hwdev);
+ for (i = 0; i < num_irqs; i++)
+ hifc_free_irq(hwdev, SERVICE_T_INTF, aeq_irqs[i].irq_id);
+}
+
+static int hifc_comm_ceqs_init(struct hifc_hwdev *hwdev)
+{
+ struct irq_info ceq_irqs[HIFC_MAX_CEQS] = {{0} };
+ u16 num_ceqs, resp_num_irq = 0, i;
+ int err;
+
+ num_ceqs = HIFC_HWIF_NUM_CEQS(hwdev->hwif);
+ if (num_ceqs > HIFC_MAX_CEQS) {
+ sdk_warn(hwdev->dev_hdl, "Adjust ceq num to %d\n",
+ HIFC_MAX_CEQS);
+ num_ceqs = HIFC_MAX_CEQS;
+ }
+
+ err = hifc_alloc_irqs(hwdev, SERVICE_T_INTF, num_ceqs, ceq_irqs,
+ &resp_num_irq);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to alloc ceq irqs, num_ceqs: %d\n",
+ num_ceqs);
+ return err;
+ }
+
+ if (resp_num_irq < num_ceqs) {
+ sdk_warn(hwdev->dev_hdl, "Adjust ceq num to %d\n",
+ resp_num_irq);
+ num_ceqs = resp_num_irq;
+ }
+
+ err = hifc_ceqs_init(hwdev, num_ceqs, ceq_irqs);
+ if (err) {
+ sdk_err(hwdev->dev_hdl,
+ "Failed to init ceqs, err:%d\n", err);
+ goto ceqs_init_err;
+ }
+
+ return 0;
+
+ceqs_init_err:
+ for (i = 0; i < num_ceqs; i++)
+ hifc_free_irq(hwdev, SERVICE_T_INTF, ceq_irqs[i].irq_id);
+
+ return err;
+}
+
+static void hifc_comm_ceqs_free(struct hifc_hwdev *hwdev)
+{
+ struct irq_info ceq_irqs[HIFC_MAX_CEQS] = {{0} };
+ u16 num_irqs;
+ int i;
+
+ hifc_get_ceq_irqs(hwdev, ceq_irqs, &num_irqs);
+ hifc_ceqs_free(hwdev);
+ for (i = 0; i < num_irqs; i++)
+ hifc_free_irq(hwdev, SERVICE_T_INTF, ceq_irqs[i].irq_id);
+}
+
+static int hifc_comm_pf_to_mgmt_init(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ if (hifc_func_type(hwdev) == TYPE_VF ||
+ !FUNC_SUPPORT_MGMT(hwdev))
+ return 0; /* VF do not support send msg to mgmt directly */
+
+ err = hifc_pf_to_mgmt_init(hwdev);
+ if (err)
+ return err;
+
+ hifc_aeq_register_hw_cb(hwdev, HIFC_MSG_FROM_MGMT_CPU,
+ hifc_mgmt_msg_aeqe_handler);
+
+ hifc_register_mgmt_msg_cb(hwdev, HIFC_MOD_COMM,
+ hwdev->pf_to_mgmt, comm_mgmt_msg_handler);
+
+ set_bit(HIFC_HWDEV_MGMT_INITED, &hwdev->func_state);
+
+ return 0;
+}
+
+static void hifc_comm_pf_to_mgmt_free(struct hifc_hwdev *hwdev)
+{
+ if (hifc_func_type(hwdev) == TYPE_VF ||
+ !FUNC_SUPPORT_MGMT(hwdev))
+ return; /* VF do not support send msg to mgmt directly */
+
+ hifc_unregister_mgmt_msg_cb(hwdev, HIFC_MOD_COMM);
+
+ hifc_aeq_unregister_hw_cb(hwdev, HIFC_MSG_FROM_MGMT_CPU);
+
+ hifc_pf_to_mgmt_free(hwdev);
+}
+
+static int hifc_comm_clp_to_mgmt_init(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ if (hifc_func_type(hwdev) == TYPE_VF ||
+ !FUNC_SUPPORT_MGMT(hwdev))
+ return 0;
+
+ err = hifc_clp_pf_to_mgmt_init(hwdev);
+ if (err)
+ return err;
+
+ set_bit(HIFC_HWDEV_CLP_INITED, &hwdev->func_state);
+
+ return 0;
+}
+
+static void hifc_comm_clp_to_mgmt_free(struct hifc_hwdev *hwdev)
+{
+ if (hifc_func_type(hwdev) == TYPE_VF ||
+ !FUNC_SUPPORT_MGMT(hwdev))
+ return;
+
+ clear_bit(HIFC_HWDEV_CLP_INITED, &hwdev->func_state);
+ hifc_clp_pf_to_mgmt_free(hwdev);
+}
+
+static int hifc_comm_cmdqs_init(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = hifc_cmdqs_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init cmd queues\n");
+ return err;
+ }
+
+ hifc_ceq_register_cb(hwdev, HIFC_CMDQ, hifc_cmdq_ceq_handler);
+
+ err = hifc_set_cmdq_depth(hwdev, HIFC_CMDQ_DEPTH);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to set cmdq depth\n");
+ goto set_cmdq_depth_err;
+ }
+
+ return 0;
+
+set_cmdq_depth_err:
+ hifc_cmdqs_free(hwdev);
+
+ return err;
+}
+
+static void hifc_comm_cmdqs_free(struct hifc_hwdev *hwdev)
+{
+ hifc_ceq_unregister_cb(hwdev, HIFC_CMDQ);
+ hifc_cmdqs_free(hwdev);
+}
+
+static int hifc_sync_mgmt_func_state(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ hifc_set_pf_status(hwdev->hwif, HIFC_PF_STATUS_ACTIVE_FLAG);
+
+ err = resources_state_set(hwdev, HIFC_RES_ACTIVE);
+ if (err) {
+ sdk_err(hwdev->dev_hdl,
+ "Failed to set function resources state\n");
+ goto resources_state_set_err;
+ }
+
+ hwdev->heartbeat_ehd.en = false;
+ if (HIFC_FUNC_TYPE(hwdev) == TYPE_PPF) {
+ /* heartbeat synchronize must be after set pf active status */
+ hifc_comm_recv_mgmt_self_cmd_reg(
+ hwdev, HIFC_MGMT_CMD_HEARTBEAT_EVENT,
+ mgmt_heartbeat_event_handler);
+ }
+
+ return 0;
+
+resources_state_set_err:
+ hifc_set_pf_status(hwdev->hwif, HIFC_PF_STATUS_INIT);
+
+ return err;
+}
+
+static void hifc_unsync_mgmt_func_state(struct hifc_hwdev *hwdev)
+{
+ hifc_set_pf_status(hwdev->hwif, HIFC_PF_STATUS_INIT);
+
+ hwdev->heartbeat_ehd.en = false;
+ if (HIFC_FUNC_TYPE(hwdev) == TYPE_PPF) {
+ hifc_comm_recv_up_self_cmd_unreg(
+ hwdev, HIFC_MGMT_CMD_HEARTBEAT_EVENT);
+ }
+
+ resources_state_set(hwdev, HIFC_RES_CLEAN);
+}
+
+int hifc_set_vport_enable(void *hwdev, bool enable)
+{
+ struct hifc_hwdev *nic_hwdev = (struct hifc_hwdev *)hwdev;
+ struct hifc_vport_state en_state = {0};
+ u16 out_size = sizeof(en_state);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &en_state.func_id);
+ if (err)
+ return err;
+
+ en_state.state = enable ? 1 : 0;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HIFC_PORT_CMD_SET_VPORT_ENABLE,
+ &en_state, sizeof(en_state),
+ &en_state, &out_size);
+ if (err || !out_size || en_state.status) {
+ sdk_err(nic_hwdev->dev_hdl, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, en_state.status, out_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int hifc_l2nic_reset_base(struct hifc_hwdev *hwdev, u16 reset_flag)
+{
+ struct hifc_l2nic_reset l2nic_reset = {0};
+ u16 out_size = sizeof(l2nic_reset);
+ int err = 0;
+
+ err = hifc_set_vport_enable(hwdev, false);
+ if (err)
+ return err;
+
+ msleep(100);
+
+ sdk_info(hwdev->dev_hdl, "L2nic reset flag 0x%x\n", reset_flag);
+
+ err = hifc_global_func_id_get(hwdev, &l2nic_reset.func_id);
+ if (err)
+ return err;
+
+ l2nic_reset.reset_flag = reset_flag;
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_L2NIC_RESET, &l2nic_reset,
+ sizeof(l2nic_reset), &l2nic_reset,
+ &out_size, 0);
+ if (err || !out_size || l2nic_reset.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to reset L2NIC resources, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, l2nic_reset.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int hifc_l2nic_reset(struct hifc_hwdev *hwdev)
+{
+ return hifc_l2nic_reset_base(hwdev, 0);
+}
+
+static int __get_func_misc_info(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = hifc_get_board_info(hwdev, &hwdev->board_info);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Get board info failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int init_func_mode(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = __get_func_misc_info(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to get function msic information\n");
+ return err;
+ }
+
+ err = hifc_l2nic_reset(hwdev);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int __init_eqs_msix_attr(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = init_aeqs_msix_attr(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init aeqs msix attr\n");
+ return err;
+ }
+
+ err = init_ceqs_msix_attr(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init ceqs msix attr\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int init_cmdqs_channel(struct hifc_hwdev *hwdev)
+{
+ u16 func_id;
+ int err;
+
+ dma_attr_table_init(hwdev);
+
+ err = hifc_comm_ceqs_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init completion event queues\n");
+ return err;
+ }
+
+ err = __init_eqs_msix_attr(hwdev);
+ if (err)
+ goto init_eqs_msix_err;
+
+ /* set default wq page_size */
+ hwdev->wq_page_size = HIFC_DEFAULT_WQ_PAGE_SIZE;
+
+ err = hifc_global_func_id_get(hwdev, &func_id);
+ if (err)
+ goto get_func_id_err;
+
+ err = hifc_set_wq_page_size(hwdev, func_id, hwdev->wq_page_size);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to set wq page size\n");
+ goto init_wq_pg_size_err;
+ }
+
+ err = hifc_comm_cmdqs_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init cmd queues\n");
+ goto cmdq_init_err;
+ }
+
+ set_bit(HIFC_HWDEV_CMDQ_INITED, &hwdev->func_state);
+
+ return 0;
+
+cmdq_init_err:
+ if (HIFC_FUNC_TYPE(hwdev) != TYPE_VF)
+ hifc_set_wq_page_size(hwdev, func_id, HIFC_HW_WQ_PAGE_SIZE);
+init_wq_pg_size_err:
+get_func_id_err:
+init_eqs_msix_err:
+ hifc_comm_ceqs_free(hwdev);
+
+ return err;
+}
+
+static int init_mgmt_channel(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = hifc_comm_clp_to_mgmt_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init clp\n");
+ return err;
+ }
+
+ err = hifc_comm_aeqs_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init async event queues\n");
+ goto aeqs_init_err;
+ }
+
+ err = hifc_comm_pf_to_mgmt_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init msg\n");
+ goto msg_init_err;
+ }
+
+ return err;
+
+msg_init_err:
+ hifc_comm_aeqs_free(hwdev);
+
+aeqs_init_err:
+ hifc_comm_clp_to_mgmt_free(hwdev);
+
+ return err;
+}
+
+/* initialize communication channel */
+int hifc_init_comm_ch(struct hifc_hwdev *hwdev)
+{
+ int err;
+
+ err = init_mgmt_channel(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init mgmt channel\n");
+ return err;
+ }
+
+ err = init_func_mode(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init function mode\n");
+ goto func_mode_err;
+ }
+
+ err = init_cmdqs_channel(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to init cmdq channel\n");
+ goto init_cmdqs_channel_err;
+ }
+
+ err = hifc_sync_mgmt_func_state(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to synchronize mgmt function state\n");
+ goto sync_mgmt_func_err;
+ }
+
+ err = hifc_aeq_register_swe_cb(hwdev, HIFC_STATELESS_EVENT,
+ hifc_nic_sw_aeqe_handler);
+ if (err) {
+ sdk_err(hwdev->dev_hdl,
+ "Failed to register ucode aeqe handler\n");
+ goto register_ucode_aeqe_err;
+ }
+
+ set_bit(HIFC_HWDEV_COMM_CH_INITED, &hwdev->func_state);
+
+ return 0;
+
+register_ucode_aeqe_err:
+ hifc_unsync_mgmt_func_state(hwdev);
+sync_mgmt_func_err:
+ return err;
+
+init_cmdqs_channel_err:
+
+func_mode_err:
+ return err;
+}
+
+static void __uninit_comm_module(struct hifc_hwdev *hwdev,
+ enum hifc_hwdev_init_state init_state)
+{
+ u16 func_id;
+
+ switch (init_state) {
+ case HIFC_HWDEV_COMM_CH_INITED:
+ hifc_aeq_unregister_swe_cb(hwdev,
+ HIFC_STATELESS_EVENT);
+ hifc_unsync_mgmt_func_state(hwdev);
+ break;
+ case HIFC_HWDEV_CMDQ_INITED:
+ hifc_comm_cmdqs_free(hwdev);
+ /* VF can set page size of 256K only, any other value
+ * will return error in pf, pf will set all vf's page
+ * size to 4K when disable sriov
+ */
+ if (HIFC_FUNC_TYPE(hwdev) != TYPE_VF) {
+ func_id = hifc_global_func_id_hw(hwdev);
+ hifc_set_wq_page_size(hwdev, func_id,
+ HIFC_HW_WQ_PAGE_SIZE);
+ }
+
+ hifc_comm_ceqs_free(hwdev);
+
+ break;
+ case HIFC_HWDEV_MBOX_INITED:
+ break;
+ case HIFC_HWDEV_MGMT_INITED:
+ hifc_comm_pf_to_mgmt_free(hwdev);
+ break;
+ case HIFC_HWDEV_AEQ_INITED:
+ hifc_comm_aeqs_free(hwdev);
+ break;
+ case HIFC_HWDEV_CLP_INITED:
+ hifc_comm_clp_to_mgmt_free(hwdev);
+ break;
+ default:
+ break;
+ }
+}
+
+#define HIFC_FUNC_STATE_BUSY_TIMEOUT 300
+void hifc_uninit_comm_ch(struct hifc_hwdev *hwdev)
+{
+ enum hifc_hwdev_init_state init_state = HIFC_HWDEV_COMM_CH_INITED;
+ int cnt;
+
+ while (init_state > HIFC_HWDEV_NONE_INITED) {
+ if (!test_bit(init_state, &hwdev->func_state)) {
+ init_state--;
+ continue;
+ }
+ clear_bit(init_state, &hwdev->func_state);
+
+ cnt = 0;
+ while (test_bit(HIFC_HWDEV_STATE_BUSY, &hwdev->func_state) &&
+ cnt++ <= HIFC_FUNC_STATE_BUSY_TIMEOUT)
+ usleep_range(900, 1000);
+
+ __uninit_comm_module(hwdev, init_state);
+
+ init_state--;
+ }
+}
+
+int hifc_slq_init(void *dev, int num_wqs)
+{
+ struct hifc_hwdev *hwdev = dev;
+ int err;
+
+ if (!dev)
+ return -EINVAL;
+
+ hwdev->wqs = kzalloc(sizeof(*hwdev->wqs), GFP_KERNEL);
+ if (!hwdev->wqs)
+ return -ENOMEM;
+
+ err = hifc_wqs_alloc(hwdev->wqs, num_wqs, hwdev->dev_hdl);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to alloc wqs\n");
+ kfree(hwdev->wqs);
+ hwdev->wqs = NULL;
+ }
+
+ return err;
+}
+
+void hifc_slq_uninit(void *dev)
+{
+ struct hifc_hwdev *hwdev = dev;
+
+ if (!hwdev)
+ return;
+
+ hifc_wqs_free(hwdev->wqs);
+
+ kfree(hwdev->wqs);
+}
+
+int hifc_slq_alloc(void *dev, u16 wqebb_size, u16 q_depth, u16 page_size,
+ u64 *cla_addr, void **handle)
+{
+ struct hifc_hwdev *hwdev = dev;
+ struct hifc_wq *wq;
+ int err;
+
+ if (!dev || !cla_addr || !handle)
+ return -EINVAL;
+
+ wq = kzalloc(sizeof(*wq), GFP_KERNEL);
+ if (!wq)
+ return -ENOMEM;
+
+ err = hifc_wq_allocate(hwdev->wqs, wq, wqebb_size, hwdev->wq_page_size,
+ q_depth, 0);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Failed to alloc wq\n");
+ kfree(wq);
+ return -EFAULT;
+ }
+
+ *cla_addr = wq->block_paddr;
+ *handle = wq;
+
+ return 0;
+}
+
+void hifc_slq_free(void *dev, void *handle)
+{
+ struct hifc_hwdev *hwdev = dev;
+
+ if (!hwdev || !handle)
+ return;
+
+ hifc_wq_free(hwdev->wqs, handle);
+ kfree(handle);
+}
+
+u64 hifc_slq_get_addr(void *handle, u16 index)
+{
+ if (!handle)
+ return 0; /* NULL of wqe addr */
+
+ return (u64)hifc_get_wqebb_addr(handle, index);
+}
+
+u64 hifc_slq_get_first_pageaddr(void *handle)
+{
+ struct hifc_wq *wq = handle;
+
+ if (!handle)
+ return 0; /* NULL of wqe addr */
+
+ return hifc_get_first_wqe_page_addr(wq);
+}
+
+int hifc_func_tmr_bitmap_set(void *hwdev, bool en)
+{
+ struct hifc_func_tmr_bitmap_op bitmap_op = {0};
+ u16 out_size = sizeof(bitmap_op);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ err = hifc_global_func_id_get(hwdev, &bitmap_op.func_idx);
+ if (err)
+ return err;
+
+ bitmap_op.ppf_idx = hifc_ppf_idx(hwdev);
+ if (en)
+ bitmap_op.op_id = FUNC_TMR_BITMAP_ENABLE;
+ else
+ bitmap_op.op_id = FUNC_TMR_BITMAP_DISABLE;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_FUNC_TMR_BITMAT_SET,
+ &bitmap_op, sizeof(bitmap_op),
+ &bitmap_op, &out_size, 0);
+ if (err || !out_size || bitmap_op.status) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to set timer bitmap, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, bitmap_op.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int ppf_ht_gpa_set(struct hifc_hwdev *hwdev, struct hifc_page_addr *pg0,
+ struct hifc_page_addr *pg1)
+{
+ struct comm_info_ht_gpa_set ht_gpa_set = {0};
+ u16 out_size = sizeof(ht_gpa_set);
+ int ret;
+
+ pg0->virt_addr = dma_zalloc_coherent(hwdev->dev_hdl,
+ HIFC_HT_GPA_PAGE_SIZE,
+ &pg0->phys_addr, GFP_KERNEL);
+ if (!pg0->virt_addr) {
+ sdk_err(hwdev->dev_hdl, "Alloc pg0 page addr failed\n");
+ return -EFAULT;
+ }
+
+ pg1->virt_addr = dma_zalloc_coherent(hwdev->dev_hdl,
+ HIFC_HT_GPA_PAGE_SIZE,
+ &pg1->phys_addr, GFP_KERNEL);
+ if (!pg1->virt_addr) {
+ sdk_err(hwdev->dev_hdl, "Alloc pg1 page addr failed\n");
+ return -EFAULT;
+ }
+
+ ht_gpa_set.page_pa0 = pg0->phys_addr;
+ ht_gpa_set.page_pa1 = pg1->phys_addr;
+ sdk_info(hwdev->dev_hdl, "PPF ht gpa set: page_addr0.pa=0x%llx, page_addr1.pa=0x%llx\n",
+ pg0->phys_addr, pg1->phys_addr);
+ ret = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_PPF_HT_GPA_SET,
+ &ht_gpa_set, sizeof(ht_gpa_set),
+ &ht_gpa_set, &out_size, 0);
+ if (ret || !out_size || ht_gpa_set.status) {
+ sdk_warn(hwdev->dev_hdl, "PPF ht gpa set failed, ret: %d, status: 0x%x, out_size: 0x%x\n",
+ ret, ht_gpa_set.status, out_size);
+ return -EFAULT;
+ }
+
+ hwdev->page_pa0.phys_addr = pg0->phys_addr;
+ hwdev->page_pa0.virt_addr = pg0->virt_addr;
+
+ hwdev->page_pa1.phys_addr = pg1->phys_addr;
+ hwdev->page_pa1.virt_addr = pg1->virt_addr;
+
+ return 0;
+}
+
+int hifc_ppf_ht_gpa_init(struct hifc_hwdev *hwdev)
+{
+ int ret;
+ int i;
+ int j;
+ int size;
+
+ struct hifc_page_addr page_addr0[HIFC_PPF_HT_GPA_SET_RETRY_TIMES];
+ struct hifc_page_addr page_addr1[HIFC_PPF_HT_GPA_SET_RETRY_TIMES];
+
+ size = HIFC_PPF_HT_GPA_SET_RETRY_TIMES * sizeof(page_addr0[0]);
+ memset(page_addr0, 0, size);
+ memset(page_addr1, 0, size);
+
+ for (i = 0; i < HIFC_PPF_HT_GPA_SET_RETRY_TIMES; i++) {
+ ret = ppf_ht_gpa_set(hwdev, &page_addr0[i], &page_addr1[i]);
+ if (!ret)
+ break;
+ }
+
+ for (j = 0; j < i; j++) {
+ if (page_addr0[j].virt_addr) {
+ dma_free_coherent(hwdev->dev_hdl,
+ HIFC_HT_GPA_PAGE_SIZE,
+ page_addr0[j].virt_addr,
+ page_addr0[j].phys_addr);
+ page_addr0[j].virt_addr = NULL;
+ }
+ if (page_addr1[j].virt_addr) {
+ dma_free_coherent(hwdev->dev_hdl,
+ HIFC_HT_GPA_PAGE_SIZE,
+ page_addr1[j].virt_addr,
+ page_addr1[j].phys_addr);
+ page_addr1[j].virt_addr = NULL;
+ }
+ }
+
+ if (i >= HIFC_PPF_HT_GPA_SET_RETRY_TIMES) {
+ sdk_err(hwdev->dev_hdl, "PPF ht gpa init failed, retry times: %d\n",
+ i);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+void hifc_ppf_ht_gpa_deinit(struct hifc_hwdev *hwdev)
+{
+ if (hwdev->page_pa0.virt_addr) {
+ dma_free_coherent(hwdev->dev_hdl, HIFC_HT_GPA_PAGE_SIZE,
+ hwdev->page_pa0.virt_addr,
+ hwdev->page_pa0.phys_addr);
+ hwdev->page_pa0.virt_addr = NULL;
+ }
+
+ if (hwdev->page_pa1.virt_addr) {
+ dma_free_coherent(hwdev->dev_hdl, HIFC_HT_GPA_PAGE_SIZE,
+ hwdev->page_pa1.virt_addr,
+ hwdev->page_pa1.phys_addr);
+ hwdev->page_pa1.virt_addr = NULL;
+ }
+}
+
+static int set_ppf_tmr_status(struct hifc_hwdev *hwdev,
+ enum ppf_tmr_status status)
+{
+ struct hifc_ppf_tmr_op op = {0};
+ u16 out_size = sizeof(op);
+ int err = 0;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (hifc_func_type(hwdev) != TYPE_PPF)
+ return -EFAULT;
+
+ if (status == HIFC_PPF_TMR_FLAG_START) {
+ err = hifc_ppf_ht_gpa_init(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "PPF ht gpa init fail!\n");
+ return -EFAULT;
+ }
+ } else {
+ hifc_ppf_ht_gpa_deinit(hwdev);
+ }
+
+ op.op_id = status;
+ op.ppf_idx = hifc_ppf_idx(hwdev);
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_PPF_TMR_SET, &op,
+ sizeof(op), &op, &out_size, 0);
+ if (err || !out_size || op.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to set ppf timer, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, op.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int hifc_ppf_tmr_start(void *hwdev)
+{
+ if (!hwdev) {
+ pr_err("Hwdev pointer is NULL for starting ppf timer\n");
+ return -EINVAL;
+ }
+
+ return set_ppf_tmr_status(hwdev, HIFC_PPF_TMR_FLAG_START);
+}
+
+int hifc_ppf_tmr_stop(void *hwdev)
+{
+ if (!hwdev) {
+ pr_err("Hwdev pointer is NULL for stop ppf timer\n");
+ return -EINVAL;
+ }
+
+ return set_ppf_tmr_status(hwdev, HIFC_PPF_TMR_FLAG_STOP);
+}
+
+int hifc_set_wq_page_size(struct hifc_hwdev *hwdev, u16 func_idx,
+ u32 page_size)
+{
+ struct hifc_wq_page_size page_size_info = {0};
+ u16 out_size = sizeof(page_size_info);
+ int err;
+
+ page_size_info.func_idx = func_idx;
+ page_size_info.ppf_idx = hifc_ppf_idx(hwdev);
+ page_size_info.page_size = HIFC_PAGE_SIZE_HW(page_size);
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_PAGESIZE_SET,
+ &page_size_info, sizeof(page_size_info),
+ &page_size_info, &out_size, 0);
+ if (err || !out_size || page_size_info.status) {
+ sdk_err(hwdev->dev_hdl, "Failed to set wq page size, err: %d, status: 0x%x, out_size: 0x%0x\n",
+ err, page_size_info.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+bool hifc_mgmt_event_ack_first(u8 mod, u8 cmd)
+{
+ if ((mod == HIFC_MOD_COMM && cmd == HIFC_MGMT_CMD_GET_HOST_INFO) ||
+ (mod == HIFC_MOD_COMM && cmd == HIFC_MGMT_CMD_HEARTBEAT_EVENT))
+ return false;
+
+ if (mod == HIFC_MOD_COMM || mod == HIFC_MOD_L2NIC ||
+ mod == HIFC_MOD_HILINK)
+ return true;
+
+ return false;
+}
+
+#define FAULT_SHOW_STR_LEN 16
+
+static void chip_fault_show(struct hifc_hwdev *hwdev,
+ struct hifc_fault_event *event)
+{
+ char fault_level[FAULT_LEVEL_MAX][FAULT_SHOW_STR_LEN + 1] = {
+ "fatal", "reset", "flr", "general", "suggestion"};
+ char level_str[FAULT_SHOW_STR_LEN + 1];
+ struct hifc_fault_event_stats *fault;
+ u8 node_id, level;
+ u32 pos, base;
+
+ fault = &hwdev->hw_stats.fault_event_stats;
+
+ memset(level_str, 0, FAULT_SHOW_STR_LEN + 1);
+ level = event->event.chip.err_level;
+ if (level < FAULT_LEVEL_MAX)
+ strncpy(level_str, fault_level[level],
+ FAULT_SHOW_STR_LEN);
+ else
+ strncpy(level_str, "Unknown", FAULT_SHOW_STR_LEN);
+
+ if (level == FAULT_LEVEL_SERIOUS_FLR) {
+ sdk_err(hwdev->dev_hdl, "err_level: %d [%s], flr func_id: %d\n",
+ level, level_str, event->event.chip.func_id);
+ atomic_inc(&fault->fault_type_stat[event->type]);
+ }
+ sdk_err(hwdev->dev_hdl, "module_id: 0x%x, err_type: 0x%x, err_level: %d[%s], err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n",
+ event->event.chip.node_id,
+ event->event.chip.err_type, level, level_str,
+ event->event.chip.err_csr_addr,
+ event->event.chip.err_csr_value);
+
+ node_id = event->event.chip.node_id;
+ atomic_inc(&fault->chip_fault_stats[node_id][level]);
+
+ base = event->event.chip.node_id * FAULT_LEVEL_MAX *
+ HIFC_CHIP_ERROR_TYPE_MAX;
+ pos = base + HIFC_CHIP_ERROR_TYPE_MAX * level +
+ event->event.chip.err_type;
+ if (pos < HIFC_CHIP_FAULT_SIZE)
+ hwdev->chip_fault_stats[pos]++;
+}
+
+static void fault_report_show(struct hifc_hwdev *hwdev,
+ struct hifc_fault_event *event)
+{
+ char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = {
+ "chip", "ucode", "mem rd timeout", "mem wr timeout",
+ "reg rd timeout", "reg wr timeout", "phy fault"};
+ char type_str[FAULT_SHOW_STR_LEN + 1];
+ struct hifc_fault_event_stats *fault;
+
+ sdk_err(hwdev->dev_hdl, "Fault event report received, func_id: %d.\n",
+ hifc_global_func_id(hwdev));
+
+ memset(type_str, 0, FAULT_SHOW_STR_LEN + 1);
+ if (event->type < FAULT_TYPE_MAX)
+ strncpy(type_str, fault_type[event->type], FAULT_SHOW_STR_LEN);
+ else
+ strncpy(type_str, "Unknown", FAULT_SHOW_STR_LEN);
+
+ sdk_err(hwdev->dev_hdl, "Fault type: %d [%s]\n", event->type, type_str);
+ sdk_err(hwdev->dev_hdl, "Fault val[0]: 0x%08x, val[1]: 0x%08x, val[2]: 0x%08x, val[3]: 0x%08x\n",
+ event->event.val[0], event->event.val[1], event->event.val[2],
+ event->event.val[3]);
+
+ fault = &hwdev->hw_stats.fault_event_stats;
+
+ switch (event->type) {
+ case FAULT_TYPE_CHIP:
+ chip_fault_show(hwdev, event);
+ break;
+ case FAULT_TYPE_UCODE:
+ atomic_inc(&fault->fault_type_stat[event->type]);
+
+ sdk_err(hwdev->dev_hdl, "cause_id: %d, core_id: %d, c_id: %d, epc: 0x%08x\n",
+ event->event.ucode.cause_id, event->event.ucode.core_id,
+ event->event.ucode.c_id, event->event.ucode.epc);
+ break;
+ case FAULT_TYPE_MEM_RD_TIMEOUT:
+ case FAULT_TYPE_MEM_WR_TIMEOUT:
+ atomic_inc(&fault->fault_type_stat[event->type]);
+
+ sdk_err(hwdev->dev_hdl, "err_csr_ctrl: 0x%08x, err_csr_data: 0x%08x, ctrl_tab: 0x%08x, mem_index: 0x%08x\n",
+ event->event.mem_timeout.err_csr_ctrl,
+ event->event.mem_timeout.err_csr_data,
+ event->event.mem_timeout.ctrl_tab,
+ event->event.mem_timeout.mem_index);
+ break;
+ case FAULT_TYPE_REG_RD_TIMEOUT:
+ case FAULT_TYPE_REG_WR_TIMEOUT:
+ atomic_inc(&fault->fault_type_stat[event->type]);
+ sdk_err(hwdev->dev_hdl, "err_csr: 0x%08x\n",
+ event->event.reg_timeout.err_csr);
+ break;
+ case FAULT_TYPE_PHY_FAULT:
+ atomic_inc(&fault->fault_type_stat[event->type]);
+ sdk_err(hwdev->dev_hdl, "op_type: %u, port_id: %u, dev_ad: %u, csr_addr: 0x%08x, op_data: 0x%08x\n",
+ event->event.phy_fault.op_type,
+ event->event.phy_fault.port_id,
+ event->event.phy_fault.dev_ad,
+ event->event.phy_fault.csr_addr,
+ event->event.phy_fault.op_data);
+ break;
+ default:
+ break;
+ }
+}
+
+static void hifc_refresh_history_fault(struct hifc_hwdev *hwdev,
+ struct hifc_fault_recover_info *info)
+{
+ if (!hwdev->history_fault_flag) {
+ hwdev->history_fault_flag = true;
+ memcpy(&hwdev->history_fault, info,
+ sizeof(struct hifc_fault_recover_info));
+ } else {
+ if (hwdev->history_fault.fault_lev >= info->fault_lev)
+ memcpy(&hwdev->history_fault, info,
+ sizeof(struct hifc_fault_recover_info));
+ }
+}
+
+static void fault_event_handler(struct hifc_hwdev *hwdev, void *buf_in,
+ u16 in_size, void *buf_out, u16 *out_size)
+{
+ struct hifc_cmd_fault_event *fault_event;
+ struct hifc_event_info event_info;
+ struct hifc_fault_info_node *fault_node;
+
+ if (in_size != sizeof(*fault_event)) {
+ sdk_err(hwdev->dev_hdl, "Invalid fault event report, length: %d, should be %ld.\n",
+ in_size, sizeof(*fault_event));
+ return;
+ }
+
+ fault_event = buf_in;
+ fault_report_show(hwdev, &fault_event->event);
+
+ if (hwdev->event_callback) {
+ event_info.type = HIFC_EVENT_FAULT;
+ memcpy(&event_info.info, &fault_event->event,
+ sizeof(event_info.info));
+
+ hwdev->event_callback(hwdev->event_pri_handle, &event_info);
+ }
+
+ /* refresh history fault info */
+ fault_node = kzalloc(sizeof(*fault_node), GFP_KERNEL);
+ if (!fault_node) {
+ sdk_err(hwdev->dev_hdl, "Malloc fault node memory failed\n");
+ return;
+ }
+
+ if (fault_event->event.type <= FAULT_TYPE_REG_WR_TIMEOUT)
+ fault_node->info.fault_src = fault_event->event.type;
+ else if (fault_event->event.type == FAULT_TYPE_PHY_FAULT)
+ fault_node->info.fault_src = HIFC_FAULT_SRC_HW_PHY_FAULT;
+
+ if (fault_node->info.fault_src == HIFC_FAULT_SRC_HW_MGMT_CHIP)
+ fault_node->info.fault_lev =
+ fault_event->event.event.chip.err_level;
+ else
+ fault_node->info.fault_lev = FAULT_LEVEL_FATAL;
+
+ memcpy(&fault_node->info.fault_data.hw_mgmt, &fault_event->event.event,
+ sizeof(union hifc_fault_hw_mgmt));
+ hifc_refresh_history_fault(hwdev, &fault_node->info);
+
+ down(&hwdev->fault_list_sem);
+ kfree(fault_node);
+ up(&hwdev->fault_list_sem);
+}
+
+static void heartbeat_lost_event_handler(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_fault_info_node *fault_node;
+ struct hifc_event_info event_info = {0};
+
+ atomic_inc(&hwdev->hw_stats.heart_lost_stats);
+ sdk_err(hwdev->dev_hdl, "Heart lost report received, func_id: %d\n",
+ hifc_global_func_id(hwdev));
+
+ if (hwdev->event_callback) {
+ event_info.type = HIFC_EVENT_HEART_LOST;
+ hwdev->event_callback(hwdev->event_pri_handle, &event_info);
+ }
+
+ /* refresh history fault info */
+ fault_node = kzalloc(sizeof(*fault_node), GFP_KERNEL);
+ if (!fault_node) {
+ sdk_err(hwdev->dev_hdl, "Malloc fault node memory failed\n");
+ return;
+ }
+
+ fault_node->info.fault_src = HIFC_FAULT_SRC_HOST_HEARTBEAT_LOST;
+ fault_node->info.fault_lev = FAULT_LEVEL_FATAL;
+ hifc_refresh_history_fault(hwdev, &fault_node->info);
+
+ down(&hwdev->fault_list_sem);
+ kfree(fault_node);
+ up(&hwdev->fault_list_sem);
+}
+
+static void sw_watchdog_timeout_info_show(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_mgmt_watchdog_info *watchdog_info;
+ u32 *dump_addr, *reg, stack_len, i, j;
+
+ if (in_size != sizeof(*watchdog_info)) {
+ sdk_err(hwdev->dev_hdl, "Invalid mgmt watchdog report, length: %d, should be %ld.\n",
+ in_size, sizeof(*watchdog_info));
+ return;
+ }
+
+ watchdog_info = buf_in;
+
+ sdk_err(hwdev->dev_hdl, "Mgmt deadloop time: 0x%x 0x%x, task id: 0x%x, sp: 0x%x\n",
+ watchdog_info->curr_time_h, watchdog_info->curr_time_l,
+ watchdog_info->task_id, watchdog_info->sp);
+ sdk_err(hwdev->dev_hdl, "Stack current used: 0x%x, peak used: 0x%x, overflow flag: 0x%x, top: 0x%x, bottom: 0x%x\n",
+ watchdog_info->curr_used, watchdog_info->peak_used,
+ watchdog_info->is_overflow, watchdog_info->stack_top,
+ watchdog_info->stack_bottom);
+
+ sdk_err(hwdev->dev_hdl, "Mgmt pc: 0x%08x, lr: 0x%08x, cpsr:0x%08x\n",
+ watchdog_info->pc, watchdog_info->lr, watchdog_info->cpsr);
+
+ sdk_err(hwdev->dev_hdl, "Mgmt register info\n");
+
+ for (i = 0; i < 3; i++) {
+ reg = watchdog_info->reg + (u64)(u32)(4 * i);
+ sdk_err(hwdev->dev_hdl, "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ *(reg), *(reg + 1), *(reg + 2), *(reg + 3));
+ }
+
+ sdk_err(hwdev->dev_hdl, "0x%08x\n", watchdog_info->reg[12]);
+
+ if (watchdog_info->stack_actlen <= 1024) {
+ stack_len = watchdog_info->stack_actlen;
+ } else {
+ sdk_err(hwdev->dev_hdl, "Oops stack length: 0x%x is wrong\n",
+ watchdog_info->stack_actlen);
+ stack_len = 1024;
+ }
+
+ sdk_err(hwdev->dev_hdl, "Mgmt dump stack, 16Bytes per line(start from sp)\n");
+ for (i = 0; i < (stack_len / 16); i++) {
+ dump_addr = (u32 *)(watchdog_info->data + ((u64)(u32)(i * 16)));
+ sdk_err(hwdev->dev_hdl, "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ *dump_addr, *(dump_addr + 1), *(dump_addr + 2),
+ *(dump_addr + 3));
+ }
+
+ for (j = 0; j < ((stack_len % 16) / 4); j++) {
+ dump_addr = (u32 *)(watchdog_info->data +
+ ((u64)(u32)(i * 16 + j * 4)));
+ sdk_err(hwdev->dev_hdl, "0x%08x ", *dump_addr);
+ }
+
+ *out_size = sizeof(*watchdog_info);
+ watchdog_info = buf_out;
+ watchdog_info->status = 0;
+}
+
+static void mgmt_watchdog_timeout_event_handler(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_fault_info_node *fault_node;
+
+ sw_watchdog_timeout_info_show(hwdev, buf_in, in_size,
+ buf_out, out_size);
+
+ /* refresh history fault info */
+ fault_node = kzalloc(sizeof(*fault_node), GFP_KERNEL);
+ if (!fault_node) {
+ sdk_err(hwdev->dev_hdl, "Malloc fault node memory failed\n");
+ return;
+ }
+
+ fault_node->info.fault_src = HIFC_FAULT_SRC_MGMT_WATCHDOG;
+ fault_node->info.fault_lev = FAULT_LEVEL_FATAL;
+ hifc_refresh_history_fault(hwdev, &fault_node->info);
+
+ down(&hwdev->fault_list_sem);
+ kfree(fault_node);
+ up(&hwdev->fault_list_sem);
+}
+
+static void mgmt_reset_event_handler(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ sdk_info(hwdev->dev_hdl, "Mgmt is reset\n");
+
+ /* mgmt reset only occurred when hot update or Mgmt deadloop,
+ * if Mgmt deadloop, mgmt will report an event with
+ * mod=0, cmd=0x56, and will reported fault to os,
+ * so mgmt reset event don't need to report fault
+ */
+}
+
+static void hifc_fmw_act_ntc_handler(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_event_info event_info = {0};
+ struct hifc_fmw_act_ntc *notice_info;
+
+ if (in_size != sizeof(*notice_info)) {
+ sdk_err(hwdev->dev_hdl, "Invalid mgmt firmware active notice, length: %d, should be %ld.\n",
+ in_size, sizeof(*notice_info));
+ return;
+ }
+
+ /* mgmt is active now, restart heartbeat enhanced detection */
+ __set_heartbeat_ehd_detect_delay(hwdev, 0);
+
+ if (!hwdev->event_callback)
+ return;
+
+ event_info.type = HIFC_EVENT_FMW_ACT_NTC;
+ hwdev->event_callback(hwdev->event_pri_handle, &event_info);
+
+ *out_size = sizeof(*notice_info);
+ notice_info = buf_out;
+ notice_info->status = 0;
+}
+
+static void hifc_pcie_dfx_event_handler(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_pcie_dfx_ntc *notice_info = buf_in;
+ struct hifc_pcie_dfx_info *dfx_info;
+ u16 size = 0;
+ u16 cnt = 0;
+ u32 num = 0;
+ u32 i, j;
+ int err;
+ u32 *reg;
+
+ if (in_size != sizeof(*notice_info)) {
+ sdk_err(hwdev->dev_hdl, "Invalid mgmt firmware active notice, length: %d, should be %ld.\n",
+ in_size, sizeof(*notice_info));
+ return;
+ }
+
+ dfx_info = kzalloc(sizeof(*dfx_info), GFP_KERNEL);
+ if (!dfx_info) {
+ sdk_err(hwdev->dev_hdl, "Malloc dfx_info memory failed\n");
+ return;
+ }
+
+ ((struct hifc_pcie_dfx_ntc *)buf_out)->status = 0;
+ *out_size = sizeof(*notice_info);
+ num = (u32)(notice_info->len / 1024);
+ sdk_info(hwdev->dev_hdl, "INFO LEN: %d\n", notice_info->len);
+ sdk_info(hwdev->dev_hdl, "PCIE DFX:\n");
+ dfx_info->host_id = 0;
+ for (i = 0; i < num; i++) {
+ dfx_info->offset = i * MAX_PCIE_DFX_BUF_SIZE;
+ if (i == (num - 1))
+ dfx_info->last = 1;
+ size = sizeof(*dfx_info);
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_PCIE_DFX_GET,
+ dfx_info, sizeof(*dfx_info),
+ dfx_info, &size, 0);
+ if (err || dfx_info->status || !size) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to get pcie dfx info, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, dfx_info->status, size);
+ kfree(dfx_info);
+ return;
+ }
+
+ reg = (u32 *)dfx_info->data;
+ for (j = 0; j < 256; j = j + 8) {
+ /*lint -save -e661 -e662*/
+ sdk_info(hwdev->dev_hdl, "0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ cnt, reg[j], reg[(u32)(j + 1)],
+ reg[(u32)(j + 2)], reg[(u32)(j + 3)],
+ reg[(u32)(j + 4)], reg[(u32)(j + 5)],
+ reg[(u32)(j + 6)], reg[(u32)(j + 7)]);
+ /*lint -restore*/
+ cnt = cnt + 32;
+ }
+ memset(dfx_info->data, 0, MAX_PCIE_DFX_BUF_SIZE);
+ }
+ kfree(dfx_info);
+}
+
+struct hifc_mctp_get_host_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 huawei_cmd;
+ u8 sub_cmd;
+ u8 rsvd[2];
+
+ u32 actual_len;
+
+ u8 data[1024];
+};
+
+static void hifc_mctp_get_host_info_event_handler(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_event_info event_info = {0};
+ struct hifc_mctp_get_host_info *mctp_out, *mctp_in;
+ struct hifc_mctp_host_info *host_info;
+
+ if (in_size != sizeof(*mctp_in)) {
+ sdk_err(hwdev->dev_hdl, "Invalid mgmt mctp info, length: %d, should be %ld\n",
+ in_size, sizeof(*mctp_in));
+ return;
+ }
+
+ *out_size = sizeof(*mctp_out);
+ mctp_out = buf_out;
+ mctp_out->status = 0;
+
+ if (!hwdev->event_callback) {
+ mctp_out->status = HIFC_MGMT_STATUS_ERR_INIT;
+ return;
+ }
+
+ mctp_in = buf_in;
+ host_info = &event_info.mctp_info;
+ host_info->major_cmd = mctp_in->huawei_cmd;
+ host_info->sub_cmd = mctp_in->sub_cmd;
+ host_info->data = mctp_out->data;
+
+ event_info.type = HIFC_EVENT_MCTP_GET_HOST_INFO;
+ hwdev->event_callback(hwdev->event_pri_handle, &event_info);
+
+ mctp_out->actual_len = host_info->data_len;
+}
+
+char *__hw_to_char_fec[HILINK_FEC_MAX_TYPE] = {"RS-FEC", "BASE-FEC", "NO-FEC"};
+
+char *__hw_to_char_port_type[LINK_PORT_MAX_TYPE] = {
+ "Unknown", "Fibre", "Electric", "Direct Attach Copper", "AOC",
+ "Back plane", "BaseT"
+};
+
+static void __get_port_type(struct hifc_hwdev *hwdev,
+ struct hifc_link_info *info, char **port_type)
+{
+ if (info->cable_absent) {
+ sdk_info(hwdev->dev_hdl, "Cable unpresent\n");
+ return;
+ }
+
+ if (info->port_type < LINK_PORT_MAX_TYPE)
+ *port_type = __hw_to_char_port_type[info->port_type];
+ else
+ sdk_info(hwdev->dev_hdl, "Unknown port type: %u\n",
+ info->port_type);
+ if (info->port_type == LINK_PORT_FIBRE) {
+ if (info->port_sub_type == FIBRE_SUBTYPE_SR)
+ *port_type = "Fibre-SR";
+ else if (info->port_sub_type == FIBRE_SUBTYPE_LR)
+ *port_type = "Fibre-LR";
+ }
+}
+
+static void __print_cable_info(struct hifc_hwdev *hwdev,
+ struct hifc_link_info *info)
+{
+ char tmp_str[512] = {0};
+ char tmp_vendor[17] = {0};
+ char *port_type = "Unknown port type";
+ int i;
+
+ __get_port_type(hwdev, info, &port_type);
+
+ for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) {
+ if (info->vendor_name[i] == ' ')
+ info->vendor_name[i] = '\0';
+ else
+ break;
+ }
+
+ memcpy(tmp_vendor, info->vendor_name,
+ sizeof(info->vendor_name));
+ snprintf(tmp_str, sizeof(tmp_str) - 1,
+ "Vendor: %s, %s, length: %um, max_speed: %uGbps",
+ tmp_vendor, port_type, info->cable_length,
+ info->cable_max_speed);
+ if (info->port_type == LINK_PORT_FIBRE ||
+ info->port_type == LINK_PORT_AOC) {
+ snprintf(tmp_str, sizeof(tmp_str) - 1,
+ "%s, %s, Temperature: %u", tmp_str,
+ info->sfp_type ? "SFP" : "QSFP", info->cable_temp);
+ if (info->sfp_type) {
+ snprintf(tmp_str, sizeof(tmp_str) - 1,
+ "%s, rx power: %uuW, tx power: %uuW",
+ tmp_str, info->power[0], info->power[1]);
+ } else {
+ snprintf(tmp_str, sizeof(tmp_str) - 1,
+ "%s, rx power: %uuw %uuW %uuW %uuW",
+ tmp_str, info->power[0], info->power[1],
+ info->power[2], info->power[3]);
+ }
+ }
+
+ sdk_info(hwdev->dev_hdl, "Cable information: %s\n",
+ tmp_str);
+}
+
+static void __hi30_lane_info(struct hifc_hwdev *hwdev,
+ struct hilink_lane *lane)
+{
+ struct hi30_ffe_data *ffe_data;
+ struct hi30_ctle_data *ctle_data;
+
+ ffe_data = (struct hi30_ffe_data *)lane->hi30_ffe;
+ ctle_data = (struct hi30_ctle_data *)lane->hi30_ctle;
+
+ sdk_info(hwdev->dev_hdl, "TX_FFE: PRE1=%s%d; PRE2=%s%d; MAIN=%d; POST1=%s%d; POST1X=%s%d\n",
+ (ffe_data->PRE1 & 0x10) ? "-" : "",
+ (int)(ffe_data->PRE1 & 0xf),
+ (ffe_data->PRE2 & 0x10) ? "-" : "",
+ (int)(ffe_data->PRE2 & 0xf),
+ (int)ffe_data->MAIN,
+ (ffe_data->POST1 & 0x10) ? "-" : "",
+ (int)(ffe_data->POST1 & 0xf),
+ (ffe_data->POST2 & 0x10) ? "-" : "",
+ (int)(ffe_data->POST2 & 0xf));
+ sdk_info(hwdev->dev_hdl, "RX_CTLE: Gain1~3=%u %u %u; Boost1~3=%u %u %u; Zero1~3=%u %u %u; Squelch1~3=%u %u %u\n",
+ ctle_data->ctlebst[0], ctle_data->ctlebst[1],
+ ctle_data->ctlebst[2], ctle_data->ctlecmband[0],
+ ctle_data->ctlecmband[1], ctle_data->ctlecmband[2],
+ ctle_data->ctlermband[0], ctle_data->ctlermband[1],
+ ctle_data->ctlermband[2], ctle_data->ctleza[0],
+ ctle_data->ctleza[1], ctle_data->ctleza[2]);
+}
+
+static void __print_hi30_status(struct hifc_hwdev *hwdev,
+ struct hifc_link_info *info)
+{
+ struct hilink_lane *lane;
+ int lane_used_num = 0, i;
+
+ for (i = 0; i < HILINK_MAX_LANE; i++) {
+ lane = (struct hilink_lane *)(info->lane2 + i * sizeof(*lane));
+ if (!lane->lane_used)
+ continue;
+
+ __hi30_lane_info(hwdev, lane);
+ lane_used_num++;
+ }
+
+ /* in new firmware, all lane info setted in lane2 */
+ if (lane_used_num)
+ return;
+
+ /* compatible old firmware */
+ __hi30_lane_info(hwdev, (struct hilink_lane *)info->lane1);
+}
+
+static void __print_link_info(struct hifc_hwdev *hwdev,
+ struct hifc_link_info *info,
+ enum hilink_info_print_event type)
+{
+ char *fec = "None";
+
+ if (info->fec < HILINK_FEC_MAX_TYPE)
+ fec = __hw_to_char_fec[info->fec];
+ else
+ sdk_info(hwdev->dev_hdl, "Unknown fec type: %u\n",
+ info->fec);
+
+ if (type == HILINK_EVENT_LINK_UP || !info->an_state) {
+ sdk_info(hwdev->dev_hdl, "Link information: speed %dGbps, %s, autoneg %s\n",
+ info->speed, fec, info->an_state ? "on" : "off");
+ } else {
+ sdk_info(hwdev->dev_hdl, "Link information: antoneg: %s\n",
+ info->an_state ? "on" : "off");
+ }
+}
+
+static char *hilink_info_report_type[HILINK_EVENT_MAX_TYPE] = {
+ "", "link up", "link down", "cable plugged"
+};
+
+void print_hilink_info(struct hifc_hwdev *hwdev,
+ enum hilink_info_print_event type,
+ struct hifc_link_info *info)
+{
+ __print_cable_info(hwdev, info);
+
+ __print_link_info(hwdev, info, type);
+
+ __print_hi30_status(hwdev, info);
+
+ if (type == HILINK_EVENT_LINK_UP)
+ return;
+
+ if (type == HILINK_EVENT_CABLE_PLUGGED) {
+ sdk_info(hwdev->dev_hdl, "alos: %u, rx_los: %u\n",
+ info->alos, info->rx_los);
+ return;
+ }
+
+ sdk_info(hwdev->dev_hdl, "PMA ctrl: %s, MAC tx %s, MAC rx %s, PMA debug info reg: 0x%x, PMA signal ok reg: 0x%x, RF/LF status reg: 0x%x\n",
+ info->pma_status == 1 ? "off" : "on",
+ info->mac_tx_en ? "enable" : "disable",
+ info->mac_rx_en ? "enable" : "disable", info->pma_dbg_info_reg,
+ info->pma_signal_ok_reg, info->rf_lf_status_reg);
+ sdk_info(hwdev->dev_hdl, "alos: %u, rx_los: %u, PCS block counter reg: 0x%x, PCS link: 0x%x, MAC link: 0x%x PCS_err_cnt: 0x%x\n",
+ info->alos, info->rx_los, info->pcs_err_blk_cnt_reg,
+ info->pcs_link_reg, info->mac_link_reg, info->pcs_err_cnt);
+}
+
+static void hifc_print_hilink_info(struct hifc_hwdev *hwdev, void *buf_in,
+ u16 in_size, void *buf_out, u16 *out_size)
+{
+ struct hifc_hilink_link_info *hilink_info = buf_in;
+ struct hifc_link_info *info;
+ enum hilink_info_print_event type;
+
+ if (in_size != sizeof(*hilink_info)) {
+ sdk_err(hwdev->dev_hdl, "Invalid hilink info message size %d, should be %ld\n",
+ in_size, sizeof(*hilink_info));
+ return;
+ }
+
+ ((struct hifc_hilink_link_info *)buf_out)->status = 0;
+ *out_size = sizeof(*hilink_info);
+
+ info = &hilink_info->info;
+ type = hilink_info->info_type;
+
+ if (type < HILINK_EVENT_LINK_UP || type >= HILINK_EVENT_MAX_TYPE) {
+ sdk_info(hwdev->dev_hdl, "Invalid hilink info report, type: %d\n",
+ type);
+ return;
+ }
+
+ sdk_info(hwdev->dev_hdl, "Hilink info report after %s\n",
+ hilink_info_report_type[type]);
+
+ print_hilink_info(hwdev, type, info);
+}
+
+static void __port_sfp_info_event(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_cmd_get_sfp_qsfp_info *sfp_info = buf_in;
+ struct hifc_port_routine_cmd *rt_cmd;
+ struct card_node *chip_node = hwdev->chip_node;
+
+ if (in_size != sizeof(*sfp_info)) {
+ sdk_err(hwdev->dev_hdl, "Invalid sfp info cmd, length: %d, should be %ld\n",
+ in_size, sizeof(*sfp_info));
+ return;
+ }
+
+ if (sfp_info->port_id >= HIFC_MAX_PORT_ID) {
+ sdk_err(hwdev->dev_hdl, "Invalid sfp port id: %d, max port is %d\n",
+ sfp_info->port_id, HIFC_MAX_PORT_ID - 1);
+ return;
+ }
+
+ if (!chip_node->rt_cmd)
+ return;
+
+ rt_cmd = &chip_node->rt_cmd[sfp_info->port_id];
+ mutex_lock(&chip_node->sfp_mutex);
+ memcpy(&rt_cmd->sfp_info, sfp_info, sizeof(rt_cmd->sfp_info));
+ rt_cmd->up_send_sfp_info = true;
+ mutex_unlock(&chip_node->sfp_mutex);
+}
+
+static void __port_sfp_abs_event(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_cmd_get_light_module_abs *sfp_abs = buf_in;
+ struct hifc_port_routine_cmd *rt_cmd;
+ struct card_node *chip_node = hwdev->chip_node;
+
+ if (in_size != sizeof(*sfp_abs)) {
+ sdk_err(hwdev->dev_hdl, "Invalid sfp absent cmd, length: %d, should be %ld\n",
+ in_size, sizeof(*sfp_abs));
+ return;
+ }
+
+ if (sfp_abs->port_id >= HIFC_MAX_PORT_ID) {
+ sdk_err(hwdev->dev_hdl, "Invalid sfp port id: %d, max port is %d\n",
+ sfp_abs->port_id, HIFC_MAX_PORT_ID - 1);
+ return;
+ }
+
+ if (!chip_node->rt_cmd)
+ return;
+
+ rt_cmd = &chip_node->rt_cmd[sfp_abs->port_id];
+ mutex_lock(&chip_node->sfp_mutex);
+ memcpy(&rt_cmd->abs, sfp_abs, sizeof(rt_cmd->abs));
+ rt_cmd->up_send_sfp_abs = true;
+ mutex_unlock(&chip_node->sfp_mutex);
+}
+
+static void mgmt_heartbeat_enhanced_event(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_heartbeat_event *hb_event = buf_in;
+ struct hifc_heartbeat_event *hb_event_out = buf_out;
+ struct hifc_hwdev *dev = hwdev;
+
+ if (in_size != sizeof(*hb_event)) {
+ sdk_err(dev->dev_hdl, "Invalid data size from mgmt for heartbeat event: %d\n",
+ in_size);
+ return;
+ }
+
+ if (dev->heartbeat_ehd.last_heartbeat != hb_event->heart) {
+ dev->heartbeat_ehd.last_update_jiffies = jiffies;
+ dev->heartbeat_ehd.last_heartbeat = hb_event->heart;
+ }
+
+ hb_event_out->drv_heart = HEARTBEAT_DRV_MAGIC_ACK;
+
+ hb_event_out->status = 0;
+ *out_size = sizeof(*hb_event_out);
+}
+
+struct dev_event_handler {
+ u8 mod;
+ u8 cmd;
+ void (*handler)(struct hifc_hwdev *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
+};
+
+struct dev_event_handler dev_cmd_handler[] = {
+ {
+ .mod = HIFC_MOD_L2NIC,
+ .cmd = HIFC_PORT_CMD_GET_SFP_INFO,
+ .handler = __port_sfp_info_event,
+ },
+
+ {
+ .mod = HIFC_MOD_L2NIC,
+ .cmd = HIFC_PORT_CMD_GET_SFP_ABS,
+ .handler = __port_sfp_abs_event,
+ },
+
+ {
+ .mod = HIFC_MOD_HILINK,
+ .cmd = HIFC_HILINK_CMD_GET_LINK_INFO,
+ .handler = hifc_print_hilink_info,
+ },
+
+ {
+ .mod = HIFC_MOD_COMM,
+ .cmd = HIFC_MGMT_CMD_FAULT_REPORT,
+ .handler = fault_event_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_L2NIC,
+ .cmd = HIFC_MGMT_CMD_HEART_LOST_REPORT,
+ .handler = heartbeat_lost_event_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_COMM,
+ .cmd = HIFC_MGMT_CMD_WATCHDOG_INFO,
+ .handler = mgmt_watchdog_timeout_event_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_L2NIC,
+ .cmd = HIFC_PORT_CMD_MGMT_RESET,
+ .handler = mgmt_reset_event_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_COMM,
+ .cmd = HIFC_MGMT_CMD_FMW_ACT_NTC,
+ .handler = hifc_fmw_act_ntc_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_COMM,
+ .cmd = HIFC_MGMT_CMD_PCIE_DFX_NTC,
+ .handler = hifc_pcie_dfx_event_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_COMM,
+ .cmd = HIFC_MGMT_CMD_GET_HOST_INFO,
+ .handler = hifc_mctp_get_host_info_event_handler,
+ },
+
+ {
+ .mod = HIFC_MOD_COMM,
+ .cmd = HIFC_MGMT_CMD_HEARTBEAT_EVENT,
+ .handler = mgmt_heartbeat_enhanced_event,
+ },
+};
+
+/* public process for this event:
+ * pf link change event
+ * pf heart lost event ,TBD
+ * pf fault report event
+ * vf link change event
+ * vf heart lost event, TBD
+ * vf fault report event, TBD
+ */
+static void _event_handler(struct hifc_hwdev *hwdev, enum hifc_mod_type mod,
+ u8 cmd, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ u32 i, size = sizeof(dev_cmd_handler) / sizeof(dev_cmd_handler[0]);
+
+ if (!hwdev)
+ return;
+
+ *out_size = 0;
+
+ for (i = 0; i < size; i++) {
+ if (cmd == dev_cmd_handler[i].cmd &&
+ mod == dev_cmd_handler[i].mod) {
+ dev_cmd_handler[i].handler(hwdev, buf_in, in_size,
+ buf_out, out_size);
+ break;
+ }
+ }
+
+ /* can't find this event cmd */
+ if (i == size)
+ sdk_warn(hwdev->dev_hdl, "Unsupported mod(%d) event cmd(%d) to process\n",
+ mod, cmd);
+}
+
+/* pf link change event */
+static void pf_nic_event_handler(void *hwdev, void *pri_handle, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_L2NIC, cmd, buf_in, in_size,
+ buf_out, out_size);
+}
+
+static void pf_hilink_event_handler(void *hwdev, void *pri_handle, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_HILINK, cmd, buf_in, in_size,
+ buf_out, out_size);
+}
+
+/* pf fault report event */
+void pf_fault_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_COMM, HIFC_MGMT_CMD_FAULT_REPORT,
+ buf_in, in_size, buf_out, out_size);
+}
+
+void mgmt_watchdog_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_COMM, HIFC_MGMT_CMD_WATCHDOG_INFO,
+ buf_in, in_size, buf_out, out_size);
+}
+
+void mgmt_fmw_act_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_COMM, HIFC_MGMT_CMD_FMW_ACT_NTC,
+ buf_in, in_size, buf_out, out_size);
+}
+
+void mgmt_pcie_dfx_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_COMM, HIFC_MGMT_CMD_PCIE_DFX_NTC,
+ buf_in, in_size, buf_out, out_size);
+}
+
+void mgmt_get_mctp_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_COMM, HIFC_MGMT_CMD_GET_HOST_INFO,
+ buf_in, in_size, buf_out, out_size);
+}
+
+void mgmt_heartbeat_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ _event_handler(hwdev, HIFC_MOD_COMM, HIFC_MGMT_CMD_HEARTBEAT_EVENT,
+ buf_in, in_size, buf_out, out_size);
+}
+
+static void pf_event_register(struct hifc_hwdev *hwdev)
+{
+ if (hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED)) {
+ hifc_register_mgmt_msg_cb(hwdev, HIFC_MOD_L2NIC,
+ hwdev, pf_nic_event_handler);
+ hifc_register_mgmt_msg_cb(hwdev, HIFC_MOD_HILINK,
+ hwdev,
+ pf_hilink_event_handler);
+ hifc_comm_recv_mgmt_self_cmd_reg(hwdev,
+ HIFC_MGMT_CMD_FAULT_REPORT,
+ pf_fault_event_handler);
+
+ hifc_comm_recv_mgmt_self_cmd_reg(hwdev,
+ HIFC_MGMT_CMD_WATCHDOG_INFO,
+ mgmt_watchdog_event_handler);
+
+ hifc_comm_recv_mgmt_self_cmd_reg(hwdev,
+ HIFC_MGMT_CMD_FMW_ACT_NTC,
+ mgmt_fmw_act_event_handler);
+ hifc_comm_recv_mgmt_self_cmd_reg(hwdev,
+ HIFC_MGMT_CMD_PCIE_DFX_NTC,
+ mgmt_pcie_dfx_event_handler);
+ hifc_comm_recv_mgmt_self_cmd_reg(hwdev,
+ HIFC_MGMT_CMD_GET_HOST_INFO,
+ mgmt_get_mctp_event_handler);
+ }
+}
+
+void hifc_event_register(void *dev, void *pri_handle,
+ hifc_event_handler callback)
+{
+ struct hifc_hwdev *hwdev = dev;
+
+ if (!dev) {
+ pr_err("Hwdev pointer is NULL for register event\n");
+ return;
+ }
+
+ hwdev->event_callback = callback;
+ hwdev->event_pri_handle = pri_handle;
+
+ pf_event_register(hwdev);
+}
+
+void hifc_event_unregister(void *dev)
+{
+ struct hifc_hwdev *hwdev = dev;
+
+ hwdev->event_callback = NULL;
+ hwdev->event_pri_handle = NULL;
+
+ hifc_unregister_mgmt_msg_cb(hwdev, HIFC_MOD_L2NIC);
+ hifc_unregister_mgmt_msg_cb(hwdev, HIFC_MOD_HILINK);
+ hifc_comm_recv_up_self_cmd_unreg(hwdev,
+ HIFC_MGMT_CMD_FAULT_REPORT);
+ hifc_comm_recv_up_self_cmd_unreg(hwdev,
+ HIFC_MGMT_CMD_WATCHDOG_INFO);
+ hifc_comm_recv_up_self_cmd_unreg(hwdev,
+ HIFC_MGMT_CMD_FMW_ACT_NTC);
+ hifc_comm_recv_up_self_cmd_unreg(hwdev,
+ HIFC_MGMT_CMD_PCIE_DFX_NTC);
+ hifc_comm_recv_up_self_cmd_unreg(hwdev,
+ HIFC_MGMT_CMD_GET_HOST_INFO);
+}
+
+/* 0 - heartbeat lost, 1 - normal */
+static u8 hifc_get_heartbeat_status(struct hifc_hwdev *hwdev)
+{
+ struct hifc_hwif *hwif = hwdev->hwif;
+ u32 attr1;
+
+ /* suprise remove should be set 1 */
+ if (!hifc_get_chip_present_flag(hwdev))
+ return 1;
+
+ attr1 = hifc_hwif_read_reg(hwif, HIFC_CSR_FUNC_ATTR1_ADDR);
+ if (attr1 == HIFC_PCIE_LINK_DOWN) {
+ sdk_err(hwdev->dev_hdl, "Detect pcie is link down\n");
+ hifc_set_chip_absent(hwdev);
+ hifc_force_complete_all(hwdev);
+ /* should notify chiperr to pangea
+ * when detecting pcie link down
+ */
+ return 1;
+ }
+
+ return HIFC_AF1_GET(attr1, MGMT_INIT_STATUS);
+}
+
+static void hifc_heartbeat_event_handler(struct work_struct *work)
+{
+ struct hifc_hwdev *hwdev =
+ container_of(work, struct hifc_hwdev, timer_work);
+ u16 out = 0;
+
+ _event_handler(hwdev, HIFC_MOD_L2NIC, HIFC_MGMT_CMD_HEART_LOST_REPORT,
+ NULL, 0, &out, &out);
+}
+
+static bool __detect_heartbeat_ehd_lost(struct hifc_hwdev *hwdev)
+{
+ struct hifc_heartbeat_enhanced *hb_ehd = &hwdev->heartbeat_ehd;
+ u64 update_time;
+ bool hb_ehd_lost = false;
+
+ if (!hb_ehd->en)
+ return false;
+
+ if (time_after(jiffies, hb_ehd->start_detect_jiffies)) {
+ update_time = jiffies_to_msecs(jiffies -
+ hb_ehd->last_update_jiffies);
+ if (update_time > HIFC_HEARBEAT_ENHANCED_LOST) {
+ sdk_warn(hwdev->dev_hdl, "Heartbeat enhanced lost for %d millisecond\n",
+ (u32)update_time);
+ hb_ehd_lost = true;
+ }
+ } else {
+ /* mgmt may not report heartbeart enhanced event and won't
+ * update last_update_jiffies
+ */
+ hb_ehd->last_update_jiffies = jiffies;
+ }
+
+ return hb_ehd_lost;
+}
+
+static void hifc_heartbeat_timer_handler(struct timer_list *t)
+{
+ struct hifc_hwdev *hwdev = from_timer(hwdev, t, heartbeat_timer);
+
+ if (__detect_heartbeat_ehd_lost(hwdev) ||
+ !hifc_get_heartbeat_status(hwdev)) {
+ hwdev->heartbeat_lost = 1;
+ queue_work(hwdev->workq, &hwdev->timer_work);
+ } else {
+ mod_timer(&hwdev->heartbeat_timer,
+ jiffies + msecs_to_jiffies(HIFC_HEARTBEAT_PERIOD));
+ }
+}
+
+void add_to_timer(struct timer_list *timer, long period)
+{
+ if (!timer)
+ return;
+
+ add_timer(timer);
+}
+
+void delete_timer(struct timer_list *timer)
+{
+ if (!timer)
+ return;
+
+ del_timer_sync(timer);
+}
+
+void hifc_init_heartbeat(struct hifc_hwdev *hwdev)
+{
+ timer_setup(&hwdev->heartbeat_timer, hifc_heartbeat_timer_handler, 0);
+ hwdev->heartbeat_timer.expires =
+ jiffies + msecs_to_jiffies(HIFC_HEARTBEAT_START_EXPIRE);
+
+ add_to_timer(&hwdev->heartbeat_timer, HIFC_HEARTBEAT_PERIOD);
+
+ INIT_WORK(&hwdev->timer_work, hifc_heartbeat_event_handler);
+}
+
+void hifc_destroy_heartbeat(struct hifc_hwdev *hwdev)
+{
+ delete_timer(&hwdev->heartbeat_timer);
+}
+
+u8 hifc_nic_sw_aeqe_handler(void *handle, u8 event, u64 data)
+{
+ struct hifc_hwdev *hwdev = (struct hifc_hwdev *)handle;
+ u8 event_level = FAULT_LEVEL_MAX;
+
+ switch (event) {
+ case HIFC_INTERNAL_TSO_FATAL_ERROR:
+ case HIFC_INTERNAL_LRO_FATAL_ERROR:
+ case HIFC_INTERNAL_TX_FATAL_ERROR:
+ case HIFC_INTERNAL_RX_FATAL_ERROR:
+ case HIFC_INTERNAL_OTHER_FATAL_ERROR:
+ atomic_inc(&hwdev->hw_stats.nic_ucode_event_stats[event]);
+ sdk_err(hwdev->dev_hdl, "SW aeqe event type: 0x%x, data: 0x%llx\n",
+ event, data);
+ event_level = FAULT_LEVEL_FATAL;
+ break;
+ default:
+ sdk_err(hwdev->dev_hdl, "Unsupported sw event %d to process.\n",
+ event);
+ }
+
+ return event_level;
+}
+
+void hifc_set_pcie_order_cfg(void *handle)
+{
+ struct hifc_hwdev *hwdev = handle;
+ u32 val;
+
+ if (!hwdev)
+ return;
+
+ val = hifc_hwif_read_reg(hwdev->hwif,
+ HIFC_GLB_DMA_SO_RO_REPLACE_ADDR);
+
+ if (HIFC_GLB_DMA_SO_RO_GET(val, SO_RO_CFG)) {
+ val = HIFC_GLB_DMA_SO_R0_CLEAR(val, SO_RO_CFG);
+ val |= HIFC_GLB_DMA_SO_R0_SET(HIFC_DISABLE_ORDER, SO_RO_CFG);
+ hifc_hwif_write_reg(hwdev->hwif,
+ HIFC_GLB_DMA_SO_RO_REPLACE_ADDR, val);
+ }
+}
+
+int hifc_get_board_info(void *hwdev, struct hifc_board_info *info)
+{
+ struct hifc_comm_board_info board_info = {0};
+ u16 out_size = sizeof(board_info);
+ int err;
+
+ if (!hwdev || !info)
+ return -EINVAL;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_GET_BOARD_INFO,
+ &board_info, sizeof(board_info),
+ &board_info, &out_size, 0);
+ if (err || board_info.status || !out_size) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, board_info.status, out_size);
+ return -EFAULT;
+ }
+
+ memcpy(info, &board_info.info, sizeof(*info));
+
+ return 0;
+}
+
+int hifc_get_phy_init_status(void *hwdev,
+ enum phy_init_status_type *init_status)
+{
+ struct hifc_phy_init_status phy_info = {0};
+ u16 out_size = sizeof(phy_info);
+ int err;
+
+ if (!hwdev || !init_status)
+ return -EINVAL;
+
+ err = hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_GET_PHY_INIT_STATUS,
+ &phy_info, sizeof(phy_info),
+ &phy_info, &out_size, 0);
+ if ((phy_info.status != HIFC_MGMT_CMD_UNSUPPORTED &&
+ phy_info.status) || err || !out_size) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to get phy info, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, phy_info.status, out_size);
+ return -EFAULT;
+ }
+
+ *init_status = phy_info.init_status;
+
+ return phy_info.status;
+}
+
+int hifc_phy_init_status_judge(void *hwdev)
+{
+ enum phy_init_status_type init_status;
+ int ret;
+ unsigned long end;
+
+ /* It's not a phy, so don't judge phy status */
+ if (!HIFC_BOARD_IS_PHY((struct hifc_hwdev *)hwdev))
+ return 0;
+
+ end = jiffies + msecs_to_jiffies(PHY_DOING_INIT_TIMEOUT);
+ do {
+ ret = hifc_get_phy_init_status(hwdev, &init_status);
+ if (ret == HIFC_MGMT_CMD_UNSUPPORTED)
+ return 0;
+ else if (ret)
+ return -EFAULT;
+
+ switch (init_status) {
+ case PHY_INIT_SUCCESS:
+ sdk_info(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Phy init is success\n");
+ return 0;
+ case PHY_NONSUPPORT:
+ sdk_info(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Phy init is nonsupport\n");
+ return 0;
+ case PHY_INIT_FAIL:
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Phy init is failed\n");
+ return -EIO;
+ case PHY_INIT_DOING:
+ msleep(250);
+ break;
+ default:
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Phy init is invalid, init_status: %d\n",
+ init_status);
+ return -EINVAL;
+ }
+ } while (time_before(jiffies, end));
+
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Phy init is timeout\n");
+
+ return -ETIMEDOUT;
+}
+
+int hifc_get_mgmt_channel_status(void *handle)
+{
+ struct hifc_hwdev *hwdev = handle;
+ u32 val;
+
+ if (!hwdev)
+ return true;
+
+ if (hifc_func_type(hwdev) == TYPE_VF ||
+ !(hwdev->feature_cap & HIFC_FUNC_SUPP_DFX_REG))
+ return false;
+
+ val = hifc_hwif_read_reg(hwdev->hwif, HIFC_ICPL_RESERVD_ADDR);
+
+ return HIFC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
+}
+
+#define HIFC_RED_REG_TIME_OUT 3000
+
+int hifc_read_reg(void *hwdev, u32 reg_addr, u32 *val)
+{
+ struct hifc_reg_info reg_info = {0};
+ u16 out_size = sizeof(reg_info);
+ int err;
+
+ if (!hwdev || !val)
+ return -EINVAL;
+
+ reg_info.reg_addr = reg_addr;
+ reg_info.val_length = sizeof(u32);
+
+ err = hifc_pf_msg_to_mgmt_sync(hwdev, HIFC_MOD_COMM,
+ HIFC_MGMT_CMD_REG_READ,
+ ®_info, sizeof(reg_info),
+ ®_info, &out_size,
+ HIFC_RED_REG_TIME_OUT);
+ if (reg_info.status || err || !out_size) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Failed to read reg, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, reg_info.status, out_size);
+ return -EFAULT;
+ }
+
+ *val = reg_info.data[0];
+
+ return 0;
+}
+
+void hifc_swe_fault_handler(struct hifc_hwdev *hwdev, u8 level,
+ u8 event, u64 val)
+{
+ struct hifc_fault_info_node *fault_node;
+
+ if (level < FAULT_LEVEL_MAX) {
+ fault_node = kzalloc(sizeof(*fault_node), GFP_KERNEL);
+ if (!fault_node) {
+ sdk_err(hwdev->dev_hdl, "Malloc fault node memory failed\n");
+ return;
+ }
+
+ fault_node->info.fault_src = HIFC_FAULT_SRC_SW_MGMT_UCODE;
+ fault_node->info.fault_lev = level;
+ fault_node->info.fault_data.sw_mgmt.event_id = event;
+ fault_node->info.fault_data.sw_mgmt.event_data = val;
+ hifc_refresh_history_fault(hwdev, &fault_node->info);
+
+ down(&hwdev->fault_list_sem);
+ kfree(fault_node);
+ up(&hwdev->fault_list_sem);
+ }
+}
+
+void hifc_set_func_deinit_flag(void *hwdev)
+{
+ struct hifc_hwdev *dev = hwdev;
+
+ set_bit(HIFC_HWDEV_FUNC_DEINIT, &dev->func_state);
+}
+
+int hifc_get_card_present_state(void *hwdev, bool *card_present_state)
+{
+ u32 addr, attr1;
+
+ if (!hwdev || !card_present_state)
+ return -EINVAL;
+
+ addr = HIFC_CSR_FUNC_ATTR1_ADDR;
+ attr1 = hifc_hwif_read_reg(((struct hifc_hwdev *)hwdev)->hwif, addr);
+ if (attr1 == HIFC_PCIE_LINK_DOWN) {
+ sdk_warn(((struct hifc_hwdev *)hwdev)->dev_hdl, "Card is not present\n");
+ *card_present_state = (bool)0;
+ } else {
+ *card_present_state = (bool)1;
+ }
+
+ return 0;
+}
+
+void hifc_disable_mgmt_msg_report(void *hwdev)
+{
+ struct hifc_hwdev *hw_dev = (struct hifc_hwdev *)hwdev;
+
+ hifc_set_pf_status(hw_dev->hwif, HIFC_PF_STATUS_INIT);
+}
+
diff --git a/drivers/scsi/huawei/hifc/hifc_hwdev.h b/drivers/scsi/huawei/hifc/hifc_hwdev.h
new file mode 100644
index 000000000000..6ebf59b31fb8
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_hwdev.h
@@ -0,0 +1,456 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_HWDEV_H_
+#define HIFC_HWDEV_H_
+
+/* to use 0-level CLA, page size must be: 64B(wqebb) * 4096(max_q_depth) */
+#define HIFC_DEFAULT_WQ_PAGE_SIZE 0x40000
+#define HIFC_HW_WQ_PAGE_SIZE 0x1000
+
+#define HIFC_MSG_TO_MGMT_MAX_LEN 2016
+
+#define HIFC_MGMT_STATUS_ERR_OK 0 /* Ok */
+#define HIFC_MGMT_STATUS_ERR_PARAM 1 /* Invalid parameter */
+#define HIFC_MGMT_STATUS_ERR_FAILED 2 /* Operation failed */
+#define HIFC_MGMT_STATUS_ERR_PORT 3 /* Invalid port */
+#define HIFC_MGMT_STATUS_ERR_TIMEOUT 4 /* Operation time out */
+#define HIFC_MGMT_STATUS_ERR_NOMATCH 5 /* Version not match */
+#define HIFC_MGMT_STATUS_ERR_EXIST 6 /* Entry exists */
+#define HIFC_MGMT_STATUS_ERR_NOMEM 7 /* Out of memory */
+#define HIFC_MGMT_STATUS_ERR_INIT 8 /* Feature not initialized */
+#define HIFC_MGMT_STATUS_ERR_FAULT 9 /* Invalid address */
+#define HIFC_MGMT_STATUS_ERR_PERM 10 /* Operation not permitted */
+#define HIFC_MGMT_STATUS_ERR_EMPTY 11 /* Table empty */
+#define HIFC_MGMT_STATUS_ERR_FULL 12 /* Table full */
+#define HIFC_MGMT_STATUS_ERR_NOT_FOUND 13 /* Not found */
+#define HIFC_MGMT_STATUS_ERR_BUSY 14 /* Device or resource busy */
+#define HIFC_MGMT_STATUS_ERR_RESOURCE 15 /* No resources for operation */
+#define HIFC_MGMT_STATUS_ERR_CONFIG 16 /* Invalid configuration */
+#define HIFC_MGMT_STATUS_ERR_UNAVAIL 17 /* Feature unavailable */
+#define HIFC_MGMT_STATUS_ERR_CRC 18 /* CRC check failed */
+#define HIFC_MGMT_STATUS_ERR_NXIO 19 /* No such device or address */
+#define HIFC_MGMT_STATUS_ERR_ROLLBACK 20 /* Chip rollback fail */
+#define HIFC_MGMT_STATUS_ERR_LEN 32 /* Length too short or too long */
+#define HIFC_MGMT_STATUS_ERR_UNSUPPORT 0xFF /* Feature not supported*/
+/* Qe buffer relates define */
+
+enum hifc_rx_buf_size {
+ HIFC_RX_BUF_SIZE_32B = 0x20,
+ HIFC_RX_BUF_SIZE_64B = 0x40,
+ HIFC_RX_BUF_SIZE_96B = 0x60,
+ HIFC_RX_BUF_SIZE_128B = 0x80,
+ HIFC_RX_BUF_SIZE_192B = 0xC0,
+ HIFC_RX_BUF_SIZE_256B = 0x100,
+ HIFC_RX_BUF_SIZE_384B = 0x180,
+ HIFC_RX_BUF_SIZE_512B = 0x200,
+ HIFC_RX_BUF_SIZE_768B = 0x300,
+ HIFC_RX_BUF_SIZE_1K = 0x400,
+ HIFC_RX_BUF_SIZE_1_5K = 0x600,
+ HIFC_RX_BUF_SIZE_2K = 0x800,
+ HIFC_RX_BUF_SIZE_3K = 0xC00,
+ HIFC_RX_BUF_SIZE_4K = 0x1000,
+ HIFC_RX_BUF_SIZE_8K = 0x2000,
+ HIFC_RX_BUF_SIZE_16K = 0x4000,
+};
+
+enum hifc_res_state {
+ HIFC_RES_CLEAN = 0,
+ HIFC_RES_ACTIVE = 1,
+};
+
+enum ppf_tmr_status {
+ HIFC_PPF_TMR_FLAG_STOP,
+ HIFC_PPF_TMR_FLAG_START,
+};
+
+struct cfg_mgmt_info;
+struct hifc_hwif;
+struct hifc_wqs;
+struct hifc_aeqs;
+struct hifc_ceqs;
+struct hifc_msg_pf_to_mgmt;
+struct hifc_cmdqs;
+
+struct hifc_root_ctxt {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u16 rsvd1;
+ u8 set_cmdq_depth;
+ u8 cmdq_depth;
+ u8 lro_en;
+ u8 rsvd2;
+ u8 ppf_idx;
+ u8 rsvd3;
+ u16 rq_depth;
+ u16 rx_buf_sz;
+ u16 sq_depth;
+};
+
+struct hifc_page_addr {
+ void *virt_addr;
+ u64 phys_addr;
+};
+
+#define HIFC_PCIE_LINK_DOWN 0xFFFFFFFF
+
+#define HIFC_DEV_ACTIVE_FW_TIMEOUT (35 * 1000)
+#define HIFC_DEV_BUSY_ACTIVE_FW 0xFE
+
+#define HIFC_HW_WQ_NAME "hifc_hardware"
+#define HIFC_HEARTBEAT_PERIOD 1000
+#define HIFC_HEARTBEAT_START_EXPIRE 5000
+
+#define HIFC_CHIP_ERROR_TYPE_MAX 1024
+#define HIFC_CHIP_FAULT_SIZE \
+ (HIFC_NODE_ID_MAX * FAULT_LEVEL_MAX * HIFC_CHIP_ERROR_TYPE_MAX)
+
+#define HIFC_CSR_DMA_ATTR_TBL_BASE 0xC80
+#define HIFC_CSR_DMA_ATTR_TBL_STRIDE 0x4
+#define HIFC_CSR_DMA_ATTR_TBL_ADDR(idx) \
+ (HIFC_CSR_DMA_ATTR_TBL_BASE \
+ + (idx) * HIFC_CSR_DMA_ATTR_TBL_STRIDE)
+
+/* MSI-X registers */
+#define HIFC_CSR_MSIX_CNT_BASE 0x2004
+#define HIFC_CSR_MSIX_STRIDE 0x8
+
+#define HIFC_CSR_MSIX_CNT_ADDR(idx) \
+ (HIFC_CSR_MSIX_CNT_BASE + (idx) * HIFC_CSR_MSIX_STRIDE)
+
+enum hifc_node_id {
+ HIFC_NODE_ID_IPSU = 4,
+ HIFC_NODE_ID_MGMT_HOST = 21, /*Host CPU send API to uP */
+ HIFC_NODE_ID_MAX = 22
+};
+
+#define HIFC_HWDEV_INIT_MODES_MASK ((1UL << HIFC_HWDEV_ALL_INITED) - 1)
+
+enum hifc_hwdev_func_state {
+ HIFC_HWDEV_FUNC_INITED = HIFC_HWDEV_ALL_INITED,
+ HIFC_HWDEV_FUNC_DEINIT,
+ HIFC_HWDEV_STATE_BUSY = 31,
+};
+
+struct hifc_cqm_stats {
+ atomic_t cqm_cmd_alloc_cnt;
+ atomic_t cqm_cmd_free_cnt;
+ atomic_t cqm_send_cmd_box_cnt;
+ atomic_t cqm_db_addr_alloc_cnt;
+ atomic_t cqm_db_addr_free_cnt;
+ atomic_t cqm_fc_srq_create_cnt;
+ atomic_t cqm_qpc_mpt_create_cnt;
+ atomic_t cqm_nonrdma_queue_create_cnt;
+ atomic_t cqm_qpc_mpt_delete_cnt;
+ atomic_t cqm_nonrdma_queue_delete_cnt;
+ atomic_t cqm_aeq_callback_cnt[112];
+};
+
+struct hifc_link_event_stats {
+ atomic_t link_down_stats;
+ atomic_t link_up_stats;
+};
+
+struct hifc_fault_event_stats {
+ atomic_t chip_fault_stats[HIFC_NODE_ID_MAX][FAULT_LEVEL_MAX];
+ atomic_t fault_type_stat[FAULT_TYPE_MAX];
+ atomic_t pcie_fault_stats;
+};
+
+struct hifc_hw_stats {
+ atomic_t heart_lost_stats;
+ atomic_t nic_ucode_event_stats[HIFC_NIC_FATAL_ERROR_MAX];
+ struct hifc_cqm_stats cqm_stats;
+ struct hifc_link_event_stats link_event_stats;
+ struct hifc_fault_event_stats fault_event_stats;
+};
+
+struct hifc_fault_info_node {
+ struct list_head list;
+ struct hifc_hwdev *hwdev;
+ struct hifc_fault_recover_info info;
+};
+
+enum heartbeat_support_state {
+ HEARTBEAT_NOT_SUPPORT = 0,
+ HEARTBEAT_SUPPORT,
+};
+
+/* 25s for max 5 heartbeat event lost */
+#define HIFC_HEARBEAT_ENHANCED_LOST 25000
+struct hifc_heartbeat_enhanced {
+ bool en; /* enable enhanced heartbeat or not */
+
+ unsigned long last_update_jiffies;
+ u32 last_heartbeat;
+
+ unsigned long start_detect_jiffies;
+};
+
+#define HIFC_CMD_VER_FUNC_ID 2
+#define HIFC_GLB_DMA_SO_RO_REPLACE_ADDR 0x488C
+#define HIFC_ICPL_RESERVD_ADDR 0x9204
+
+#define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, out_size)\
+ hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_L2NIC, cmd, \
+ buf_in, in_size, \
+ buf_out, out_size, 0)
+
+struct hifc_hwdev {
+ void *adapter_hdl; /* pointer to hifc_pcidev or NDIS_Adapter */
+ void *pcidev_hdl; /* pointer to pcidev or Handler */
+ void *dev_hdl; /* pointer to pcidev->dev or Handler, for
+ * sdk_err() or dma_alloc()
+ */
+ u32 wq_page_size;
+
+ void *cqm_hdl;
+ void *chip_node;
+
+ struct hifc_hwif *hwif; /* include void __iomem *bar */
+ struct cfg_mgmt_info *cfg_mgmt;
+ struct hifc_wqs *wqs; /* for FC slq */
+
+ struct hifc_aeqs *aeqs;
+ struct hifc_ceqs *ceqs;
+
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ struct hifc_clp_pf_to_mgmt *clp_pf_to_mgmt;
+
+ struct hifc_cmdqs *cmdqs;
+
+ struct hifc_page_addr page_pa0;
+ struct hifc_page_addr page_pa1;
+
+ hifc_event_handler event_callback;
+ void *event_pri_handle;
+ bool history_fault_flag;
+ struct hifc_fault_recover_info history_fault;
+ struct semaphore fault_list_sem;
+
+ struct work_struct timer_work;
+ struct workqueue_struct *workq;
+ struct timer_list heartbeat_timer;
+ /* true represent heartbeat lost, false represent heartbeat restore */
+ u32 heartbeat_lost;
+ int chip_present_flag;
+ struct hifc_heartbeat_enhanced heartbeat_ehd;
+ struct hifc_hw_stats hw_stats;
+ u8 *chip_fault_stats;
+
+ u32 statufull_ref_cnt;
+ ulong func_state;
+
+ u64 feature_cap; /* enum hifc_func_cap */
+
+ /* In bmgw x86 host, driver can't send message to mgmt cpu directly,
+ * need to trasmit message ppf mbox to bmgw arm host.
+ */
+
+ struct hifc_board_info board_info;
+};
+
+int hifc_init_comm_ch(struct hifc_hwdev *hwdev);
+void hifc_uninit_comm_ch(struct hifc_hwdev *hwdev);
+
+enum hifc_set_arm_type {
+ HIFC_SET_ARM_CMDQ,
+ HIFC_SET_ARM_SQ,
+ HIFC_SET_ARM_TYPE_NUM,
+};
+
+/* up to driver event */
+#define HIFC_PORT_CMD_MGMT_RESET 0x0
+struct hifc_vport_state {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 state;
+ u8 rsvd2[3];
+};
+
+struct hifc_l2nic_reset {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 reset_flag;
+};
+
+/* HILINK module interface */
+
+/* cmd of mgmt CPU message for HILINK module */
+enum hifc_hilink_cmd {
+ HIFC_HILINK_CMD_GET_LINK_INFO = 0x3,
+ HIFC_HILINK_CMD_SET_LINK_SETTINGS = 0x8,
+};
+
+enum hilink_info_print_event {
+ HILINK_EVENT_LINK_UP = 1,
+ HILINK_EVENT_LINK_DOWN,
+ HILINK_EVENT_CABLE_PLUGGED,
+ HILINK_EVENT_MAX_TYPE,
+};
+
+enum hifc_link_port_type {
+ LINK_PORT_FIBRE = 1,
+ LINK_PORT_ELECTRIC,
+ LINK_PORT_COPPER,
+ LINK_PORT_AOC,
+ LINK_PORT_BACKPLANE,
+ LINK_PORT_BASET,
+ LINK_PORT_MAX_TYPE,
+};
+
+enum hilink_fibre_subtype {
+ FIBRE_SUBTYPE_SR = 1,
+ FIBRE_SUBTYPE_LR,
+ FIBRE_SUBTYPE_MAX,
+};
+
+enum hilink_fec_type {
+ HILINK_FEC_RSFEC,
+ HILINK_FEC_BASEFEC,
+ HILINK_FEC_NOFEC,
+ HILINK_FEC_MAX_TYPE,
+};
+
+/* cmd of mgmt CPU message */
+enum hifc_port_cmd {
+ HIFC_PORT_CMD_SET_MAC = 0x9,
+ HIFC_PORT_CMD_GET_AUTONEG_CAP = 0xf,
+ HIFC_PORT_CMD_SET_VPORT_ENABLE = 0x5d,
+ HIFC_PORT_CMD_UPDATE_MAC = 0xa4,
+ HIFC_PORT_CMD_GET_SFP_INFO = 0xad,
+ HIFC_PORT_CMD_GET_STD_SFP_INFO = 0xF0,
+ HIFC_PORT_CMD_GET_SFP_ABS = 0xFB,
+};
+
+struct hi30_ffe_data {
+ u8 PRE2;
+ u8 PRE1;
+ u8 POST1;
+ u8 POST2;
+ u8 MAIN;
+};
+
+struct hi30_ctle_data {
+ u8 ctlebst[3];
+ u8 ctlecmband[3];
+ u8 ctlermband[3];
+ u8 ctleza[3];
+ u8 ctlesqh[3];
+ u8 ctleactgn[3];
+ u8 ctlepassgn;
+};
+
+#define HILINK_MAX_LANE 4
+
+struct hilink_lane {
+ u8 lane_used;
+ u8 hi30_ffe[5];
+ u8 hi30_ctle[19];
+ u8 hi30_dfe[14];
+ u8 rsvd4;
+};
+
+struct hifc_link_info {
+ u8 vendor_name[16];
+ /* port type:
+ * 1 - fiber; 2 - electric; 3 - copper; 4 - AOC; 5 - backplane;
+ * 6 - baseT; 0xffff - unknown
+ *
+ * port subtype:
+ * Only when port_type is fiber:
+ * 1 - SR; 2 - LR
+ */
+ u32 port_type;
+ u32 port_sub_type;
+ u32 cable_length;
+ u8 cable_temp;
+ u8 cable_max_speed; /* 1(G)/10(G)/25(G)... */
+ u8 sfp_type; /* 0 - qsfp; 1 - sfp */
+ u8 rsvd0;
+ u32 power[4]; /* uW; if is sfp, only power[2] is valid */
+
+ u8 an_state; /* 0 - off; 1 - on */
+ u8 fec; /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */
+ u16 speed; /* 1(G)/10(G)/25(G)... */
+
+ u8 cable_absent; /* 0 - cable present; 1 - cable unpresent */
+ u8 alos; /* 0 - yes; 1 - no */
+ u8 rx_los; /* 0 - yes; 1 - no */
+ u8 pma_status;
+ u32 pma_dbg_info_reg; /* pma debug info: */
+ u32 pma_signal_ok_reg; /* signal ok: */
+
+ u32 pcs_err_blk_cnt_reg; /* error block counter: */
+ u32 rf_lf_status_reg; /* RF/LF status: */
+ u8 pcs_link_reg; /* pcs link: */
+ u8 mac_link_reg; /* mac link: */
+ u8 mac_tx_en;
+ u8 mac_rx_en;
+ u32 pcs_err_cnt;
+
+ /* struct hifc_hilink_lane: 40 bytes */
+ u8 lane1[40]; /* 25GE lane in old firmware */
+
+ u8 rsvd1[266]; /* hilink machine state */
+
+ u8 lane2[HILINK_MAX_LANE * 40]; /* max 4 lane for 40GE/100GE */
+
+ u8 rsvd2[2];
+};
+
+struct hifc_hilink_link_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 port_id;
+ u8 info_type; /* 1: link up 2: link down 3 cable plugged */
+ u8 rsvd1;
+
+ struct hifc_link_info info;
+
+ u8 rsvd2[352];
+};
+
+int hifc_set_arm_bit(void *hwdev, enum hifc_set_arm_type q_type, u16 q_id);
+void hifc_set_chip_present(void *hwdev);
+void hifc_force_complete_all(void *hwdev);
+void hifc_init_heartbeat(struct hifc_hwdev *hwdev);
+void hifc_destroy_heartbeat(struct hifc_hwdev *hwdev);
+u8 hifc_nic_sw_aeqe_handler(void *handle, u8 event, u64 data);
+int hifc_l2nic_reset_base(struct hifc_hwdev *hwdev, u16 reset_flag);
+int hifc_pf_msg_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size, u32 timeout);
+void hifc_swe_fault_handler(struct hifc_hwdev *hwdev, u8 level,
+ u8 event, u64 val);
+bool hifc_mgmt_event_ack_first(u8 mod, u8 cmd);
+int hifc_phy_init_status_judge(void *hwdev);
+int hifc_api_csr_rd32(void *hwdev, u8 dest, u32 addr, u32 *val);
+int hifc_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val);
+void mgmt_heartbeat_event_handler(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
+struct hifc_sge {
+ u32 hi_addr;
+ u32 lo_addr;
+ u32 len;
+};
+
+void hifc_cpu_to_be32(void *data, int len);
+void hifc_be32_to_cpu(void *data, int len);
+void hifc_set_sge(struct hifc_sge *sge, dma_addr_t addr, u32 len);
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_hwif.c b/drivers/scsi/huawei/hifc/hifc_hwif.c
new file mode 100644
index 000000000000..ec84c9bc2f2f
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_hwif.c
@@ -0,0 +1,630 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/io-mapping.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_eqs.h"
+
+#define WAIT_HWIF_READY_TIMEOUT 10000
+#define HIFC_SELFTEST_RESULT 0x883C
+
+u32 hifc_hwif_read_reg(struct hifc_hwif *hwif, u32 reg)
+{
+ return be32_to_cpu(readl(hwif->cfg_regs_base + reg));
+}
+
+void hifc_hwif_write_reg(struct hifc_hwif *hwif, u32 reg, u32 val)
+{
+ writel(cpu_to_be32(val), hwif->cfg_regs_base + reg);
+}
+
+/**
+ * hwif_ready - test if the HW initialization passed
+ * @hwdev: the pointer to hw device
+ * Return: 0 - success, negative - failure
+ **/
+static int hwif_ready(struct hifc_hwdev *hwdev)
+{
+ u32 addr, attr1;
+
+ addr = HIFC_CSR_FUNC_ATTR1_ADDR;
+ attr1 = hifc_hwif_read_reg(hwdev->hwif, addr);
+
+ if (attr1 == HIFC_PCIE_LINK_DOWN)
+ return -EBUSY;
+
+ if (!HIFC_AF1_GET(attr1, MGMT_INIT_STATUS))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int wait_hwif_ready(struct hifc_hwdev *hwdev)
+{
+ ulong timeout = 0;
+
+ do {
+ if (!hwif_ready(hwdev))
+ return 0;
+
+ usleep_range(999, 1000);
+ timeout++;
+ } while (timeout <= WAIT_HWIF_READY_TIMEOUT);
+
+ sdk_err(hwdev->dev_hdl, "Wait for hwif timeout\n");
+ return -EBUSY;
+}
+
+/**
+ * set_hwif_attr - set the attributes as members in hwif
+ * @hwif: the hardware interface of a pci function device
+ * @attr0: the first attribute that was read from the hw
+ * @attr1: the second attribute that was read from the hw
+ * @attr2: the third attribute that was read from the hw
+ **/
+static void set_hwif_attr(struct hifc_hwif *hwif, u32 attr0, u32 attr1,
+ u32 attr2)
+{
+ hwif->attr.func_global_idx = HIFC_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+ hwif->attr.port_to_port_idx = HIFC_AF0_GET(attr0, P2P_IDX);
+ hwif->attr.pci_intf_idx = HIFC_AF0_GET(attr0, PCI_INTF_IDX);
+ hwif->attr.vf_in_pf = HIFC_AF0_GET(attr0, VF_IN_PF);
+ hwif->attr.func_type = HIFC_AF0_GET(attr0, FUNC_TYPE);
+
+ hwif->attr.ppf_idx = HIFC_AF1_GET(attr1, PPF_IDX);
+
+ hwif->attr.num_aeqs = BIT(HIFC_AF1_GET(attr1, AEQS_PER_FUNC));
+ hwif->attr.num_ceqs = BIT(HIFC_AF1_GET(attr1, CEQS_PER_FUNC));
+ hwif->attr.num_irqs = BIT(HIFC_AF1_GET(attr1, IRQS_PER_FUNC));
+ hwif->attr.num_dma_attr = BIT(HIFC_AF1_GET(attr1, DMA_ATTR_PER_FUNC));
+}
+
+/**
+ * get_hwif_attr - read and set the attributes as members in hwif
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void get_hwif_attr(struct hifc_hwif *hwif)
+{
+ u32 addr, attr0, attr1, attr2;
+
+ addr = HIFC_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hifc_hwif_read_reg(hwif, addr);
+
+ addr = HIFC_CSR_FUNC_ATTR1_ADDR;
+ attr1 = hifc_hwif_read_reg(hwif, addr);
+
+ addr = HIFC_CSR_FUNC_ATTR2_ADDR;
+ attr2 = hifc_hwif_read_reg(hwif, addr);
+
+ set_hwif_attr(hwif, attr0, attr1, attr2);
+}
+
+void hifc_set_pf_status(struct hifc_hwif *hwif, enum hifc_pf_status status)
+{
+ u32 attr5 = HIFC_AF5_SET(status, PF_STATUS);
+ u32 addr = HIFC_CSR_FUNC_ATTR5_ADDR;
+
+ hifc_hwif_write_reg(hwif, addr, attr5);
+}
+
+enum hifc_pf_status hifc_get_pf_status(struct hifc_hwif *hwif)
+{
+ u32 attr5 = hifc_hwif_read_reg(hwif, HIFC_CSR_FUNC_ATTR5_ADDR);
+
+ return HIFC_AF5_GET(attr5, PF_STATUS);
+}
+
+enum hifc_doorbell_ctrl hifc_get_doorbell_ctrl_status(struct hifc_hwif *hwif)
+{
+ u32 attr4 = hifc_hwif_read_reg(hwif, HIFC_CSR_FUNC_ATTR4_ADDR);
+
+ return HIFC_AF4_GET(attr4, DOORBELL_CTRL);
+}
+
+enum hifc_outbound_ctrl hifc_get_outbound_ctrl_status(struct hifc_hwif *hwif)
+{
+ u32 attr4 = hifc_hwif_read_reg(hwif, HIFC_CSR_FUNC_ATTR4_ADDR);
+
+ return HIFC_AF4_GET(attr4, OUTBOUND_CTRL);
+}
+
+void hifc_enable_doorbell(struct hifc_hwif *hwif)
+{
+ u32 addr, attr4;
+
+ addr = HIFC_CSR_FUNC_ATTR4_ADDR;
+ attr4 = hifc_hwif_read_reg(hwif, addr);
+
+ attr4 = HIFC_AF4_CLEAR(attr4, DOORBELL_CTRL);
+ attr4 |= HIFC_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL);
+
+ hifc_hwif_write_reg(hwif, addr, attr4);
+}
+
+void hifc_disable_doorbell(struct hifc_hwif *hwif)
+{
+ u32 addr, attr4;
+
+ addr = HIFC_CSR_FUNC_ATTR4_ADDR;
+ attr4 = hifc_hwif_read_reg(hwif, addr);
+
+ attr4 = HIFC_AF4_CLEAR(attr4, DOORBELL_CTRL);
+ attr4 |= HIFC_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL);
+
+ hifc_hwif_write_reg(hwif, addr, attr4);
+}
+
+/**
+ * set_ppf - try to set hwif as ppf and set the type of hwif in this case
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void set_ppf(struct hifc_hwif *hwif)
+{
+ struct hifc_func_attr *attr = &hwif->attr;
+ u32 addr, val, ppf_election;
+
+ /* Read Modify Write */
+ addr = HIFC_CSR_PPF_ELECTION_ADDR;
+
+ val = hifc_hwif_read_reg(hwif, addr);
+ val = HIFC_PPF_ELECTION_CLEAR(val, IDX);
+
+ ppf_election = HIFC_PPF_ELECTION_SET(attr->func_global_idx, IDX);
+ val |= ppf_election;
+
+ hifc_hwif_write_reg(hwif, addr, val);
+
+ /* Check PPF */
+ val = hifc_hwif_read_reg(hwif, addr);
+
+ attr->ppf_idx = HIFC_PPF_ELECTION_GET(val, IDX);
+ if (attr->ppf_idx == attr->func_global_idx)
+ attr->func_type = TYPE_PPF;
+}
+
+/**
+ * get_mpf - get the mpf index into the hwif
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void get_mpf(struct hifc_hwif *hwif)
+{
+ struct hifc_func_attr *attr = &hwif->attr;
+ u32 mpf_election, addr;
+
+ addr = HIFC_CSR_GLOBAL_MPF_ELECTION_ADDR;
+
+ mpf_election = hifc_hwif_read_reg(hwif, addr);
+ attr->mpf_idx = HIFC_MPF_ELECTION_GET(mpf_election, IDX);
+}
+
+/**
+ * set_mpf - try to set hwif as mpf and set the mpf idx in hwif
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void set_mpf(struct hifc_hwif *hwif)
+{
+ struct hifc_func_attr *attr = &hwif->attr;
+ u32 addr, val, mpf_election;
+
+ /* Read Modify Write */
+ addr = HIFC_CSR_GLOBAL_MPF_ELECTION_ADDR;
+
+ val = hifc_hwif_read_reg(hwif, addr);
+
+ val = HIFC_MPF_ELECTION_CLEAR(val, IDX);
+ mpf_election = HIFC_MPF_ELECTION_SET(attr->func_global_idx, IDX);
+
+ val |= mpf_election;
+ hifc_hwif_write_reg(hwif, addr, val);
+}
+
+static void init_db_area_idx(struct hifc_free_db_area *free_db_area)
+{
+ u32 i;
+
+ for (i = 0; i < HIFC_DB_MAX_AREAS; i++)
+ free_db_area->db_idx[i] = i;
+
+ free_db_area->num_free = HIFC_DB_MAX_AREAS;
+
+ spin_lock_init(&free_db_area->idx_lock);
+}
+
+static int get_db_idx(struct hifc_hwif *hwif, u32 *idx)
+{
+ struct hifc_free_db_area *free_db_area = &hwif->free_db_area;
+ u32 pos;
+ u32 pg_idx;
+
+ spin_lock(&free_db_area->idx_lock);
+
+retry:
+ if (free_db_area->num_free == 0) {
+ spin_unlock(&free_db_area->idx_lock);
+ return -ENOMEM;
+ }
+
+ free_db_area->num_free--;
+
+ pos = free_db_area->alloc_pos++;
+ pos &= HIFC_DB_MAX_AREAS - 1;
+
+ pg_idx = free_db_area->db_idx[pos];
+
+ free_db_area->db_idx[pos] = 0xFFFFFFFF;
+
+ /* pg_idx out of range */
+ if (pg_idx >= HIFC_DB_MAX_AREAS)
+ goto retry;
+
+ spin_unlock(&free_db_area->idx_lock);
+
+ *idx = pg_idx;
+
+ return 0;
+}
+
+static void free_db_idx(struct hifc_hwif *hwif, u32 idx)
+{
+ struct hifc_free_db_area *free_db_area = &hwif->free_db_area;
+ u32 pos;
+
+ if (idx >= HIFC_DB_MAX_AREAS)
+ return;
+
+ spin_lock(&free_db_area->idx_lock);
+
+ pos = free_db_area->return_pos++;
+ pos &= HIFC_DB_MAX_AREAS - 1;
+
+ free_db_area->db_idx[pos] = idx;
+
+ free_db_area->num_free++;
+
+ spin_unlock(&free_db_area->idx_lock);
+}
+
+void hifc_free_db_addr(void *hwdev, void __iomem *db_base,
+ void __iomem *dwqe_base)
+{
+ struct hifc_hwif *hwif;
+ u32 idx;
+
+ if (!hwdev || !db_base)
+ return;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+ idx = DB_IDX(db_base, hwif->db_base);
+
+#if defined(__aarch64__)
+ /* No need to unmap */
+#else
+ if (dwqe_base)
+ io_mapping_unmap(dwqe_base);
+#endif
+
+ free_db_idx(hwif, idx);
+}
+
+int hifc_alloc_db_addr(void *hwdev, void __iomem **db_base,
+ void __iomem **dwqe_base)
+{
+ struct hifc_hwif *hwif;
+ u64 offset;
+ u32 idx;
+ int err;
+
+ if (!hwdev || !db_base)
+ return -EINVAL;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ err = get_db_idx(hwif, &idx);
+ if (err)
+ return -EFAULT;
+
+ *db_base = hwif->db_base + idx * HIFC_DB_PAGE_SIZE;
+
+ if (!dwqe_base)
+ return 0;
+
+ offset = ((u64)idx) << PAGE_SHIFT;
+
+#if defined(__aarch64__)
+ *dwqe_base = hwif->dwqe_mapping + offset;
+#else
+ *dwqe_base = io_mapping_map_wc(hwif->dwqe_mapping, offset,
+ HIFC_DB_PAGE_SIZE);
+#endif
+
+ if (!(*dwqe_base)) {
+ hifc_free_db_addr(hwdev, *db_base, NULL);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+void hifc_set_msix_state(void *hwdev, u16 msix_idx, enum hifc_msix_state flag)
+{
+ struct hifc_hwif *hwif;
+ u32 offset = msix_idx * HIFC_PCI_MSIX_ENTRY_SIZE +
+ HIFC_PCI_MSIX_ENTRY_VECTOR_CTRL;
+ u32 mask_bits;
+
+ if (!hwdev)
+ return;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ mask_bits = readl(hwif->intr_regs_base + offset);
+ mask_bits &= ~HIFC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
+ if (flag)
+ mask_bits |= HIFC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
+
+ writel(mask_bits, hwif->intr_regs_base + offset);
+}
+
+static void disable_all_msix(struct hifc_hwdev *hwdev)
+{
+ u16 num_irqs = hwdev->hwif->attr.num_irqs;
+ u16 i;
+
+ for (i = 0; i < num_irqs; i++)
+ hifc_set_msix_state(hwdev, i, HIFC_MSIX_DISABLE);
+}
+
+static int wait_until_doorbell_and_outbound_enabled(struct hifc_hwif *hwif)
+{
+ enum hifc_doorbell_ctrl db_ctrl;
+ enum hifc_outbound_ctrl outbound_ctrl;
+ u32 cnt = 0;
+
+ while (cnt < HIFC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT) {
+ db_ctrl = hifc_get_doorbell_ctrl_status(hwif);
+ outbound_ctrl = hifc_get_outbound_ctrl_status(hwif);
+
+ if (outbound_ctrl == ENABLE_OUTBOUND &&
+ db_ctrl == ENABLE_DOORBELL)
+ return 0;
+
+ usleep_range(900, 1000);
+ cnt++;
+ }
+
+ return -EFAULT;
+}
+
+static void __print_selftest_reg(struct hifc_hwdev *hwdev)
+{
+ u32 addr, attr0, attr1;
+
+ addr = HIFC_CSR_FUNC_ATTR1_ADDR;
+ attr1 = hifc_hwif_read_reg(hwdev->hwif, addr);
+
+ if (attr1 == HIFC_PCIE_LINK_DOWN) {
+ sdk_err(hwdev->dev_hdl, "PCIE is link down\n");
+ return;
+ }
+
+ addr = HIFC_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hifc_hwif_read_reg(hwdev->hwif, addr);
+ if (HIFC_AF0_GET(attr0, FUNC_TYPE) != TYPE_VF &&
+ !HIFC_AF0_GET(attr0, PCI_INTF_IDX))
+ sdk_err(hwdev->dev_hdl, "Selftest reg: 0x%08x\n",
+ hifc_hwif_read_reg(hwdev->hwif,
+ HIFC_SELFTEST_RESULT));
+}
+
+/**
+ * hifc_init_hwif - initialize the hw interface
+ * @hwdev: the pointer to hw device
+ * @cfg_reg_base: configuration base address
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_init_hwif(struct hifc_hwdev *hwdev, void *cfg_reg_base,
+ void *intr_reg_base, u64 db_base_phy,
+ void *db_base, void *dwqe_mapping)
+{
+ struct hifc_hwif *hwif;
+ int err;
+
+ hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+ if (!hwif)
+ return -ENOMEM;
+
+ hwdev->hwif = hwif;
+ hwif->pdev = hwdev->pcidev_hdl;
+
+ hwif->cfg_regs_base = cfg_reg_base;
+ hwif->intr_regs_base = intr_reg_base;
+
+ hwif->db_base_phy = db_base_phy;
+ hwif->db_base = db_base;
+ hwif->dwqe_mapping = dwqe_mapping;
+ init_db_area_idx(&hwif->free_db_area);
+
+ err = wait_hwif_ready(hwdev);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Chip status is not ready\n");
+ __print_selftest_reg(hwdev);
+ goto hwif_ready_err;
+ }
+
+ get_hwif_attr(hwif);
+
+ err = wait_until_doorbell_and_outbound_enabled(hwif);
+ if (err) {
+ sdk_err(hwdev->dev_hdl, "Hw doorbell/outbound is disabled\n");
+ goto hwif_ready_err;
+ }
+
+ set_ppf(hwif);
+
+ if (HIFC_IS_PPF(hwdev))
+ set_mpf(hwif);
+
+ get_mpf(hwif);
+
+ disable_all_msix(hwdev);
+ /* disable mgmt cpu report any event */
+ hifc_set_pf_status(hwdev->hwif, HIFC_PF_STATUS_INIT);
+
+ pr_info("global_func_idx: %d, func_type: %d, host_id: %d, ppf: %d, mpf: %d\n",
+ hwif->attr.func_global_idx, hwif->attr.func_type,
+ hwif->attr.pci_intf_idx, hwif->attr.ppf_idx,
+ hwif->attr.mpf_idx);
+
+ return 0;
+
+hwif_ready_err:
+ kfree(hwif);
+
+ return err;
+}
+
+/**
+ * hifc_free_hwif - free the hw interface
+ * @hwdev: the pointer to hw device
+ **/
+void hifc_free_hwif(struct hifc_hwdev *hwdev)
+{
+ kfree(hwdev->hwif);
+}
+
+int hifc_dma_zalloc_coherent_align(void *dev_hdl, u64 size, u64 align,
+ unsigned flag,
+ struct hifc_dma_addr_align *mem_align)
+{
+ void *vaddr, *align_vaddr;
+ dma_addr_t paddr, align_paddr;
+ u64 real_size = size;
+
+ vaddr = dma_zalloc_coherent(dev_hdl, real_size, &paddr, flag);
+ if (!vaddr)
+ return -ENOMEM;
+
+ align_paddr = ALIGN(paddr, align);
+ /* align */
+ if (align_paddr == paddr) {
+ align_vaddr = vaddr;
+ goto out;
+ }
+
+ dma_free_coherent(dev_hdl, real_size, vaddr, paddr);
+
+ /* realloc memory for align */
+ real_size = size + align;
+ vaddr = dma_zalloc_coherent(dev_hdl, real_size, &paddr, flag);
+ if (!vaddr)
+ return -ENOMEM;
+
+ align_paddr = ALIGN(paddr, align);
+ align_vaddr = (void *)((u64)vaddr + (align_paddr - paddr));
+
+out:
+ mem_align->real_size = (u32)real_size;
+ mem_align->ori_vaddr = vaddr;
+ mem_align->ori_paddr = paddr;
+ mem_align->align_vaddr = align_vaddr;
+ mem_align->align_paddr = align_paddr;
+
+ return 0;
+}
+
+void hifc_dma_free_coherent_align(void *dev_hdl,
+ struct hifc_dma_addr_align *mem_align)
+{
+ dma_free_coherent(dev_hdl, mem_align->real_size,
+ mem_align->ori_vaddr, mem_align->ori_paddr);
+}
+
+u16 hifc_global_func_id(void *hwdev)
+{
+ struct hifc_hwif *hwif;
+
+ if (!hwdev)
+ return 0;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ return hwif->attr.func_global_idx;
+}
+
+/**
+ * get function id from register,used by sriov hot migration process
+ * @hwdev: the pointer to hw device
+ **/
+u16 hifc_global_func_id_hw(void *hwdev)
+{
+ u32 addr, attr0;
+ struct hifc_hwdev *dev;
+
+ dev = (struct hifc_hwdev *)hwdev;
+ addr = HIFC_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hifc_hwif_read_reg(dev->hwif, addr);
+
+ return HIFC_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+}
+
+/**
+ * get function id, used by sriov hot migratition process.
+ * @hwdev: the pointer to hw device
+ * @func_id: function id
+ **/
+int hifc_global_func_id_get(void *hwdev, u16 *func_id)
+{
+ *func_id = hifc_global_func_id(hwdev);
+ return 0;
+}
+
+u8 hifc_pcie_itf_id(void *hwdev)
+{
+ struct hifc_hwif *hwif;
+
+ if (!hwdev)
+ return 0;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ return hwif->attr.pci_intf_idx;
+}
+EXPORT_SYMBOL(hifc_pcie_itf_id);
+
+enum func_type hifc_func_type(void *hwdev)
+{
+ struct hifc_hwif *hwif;
+
+ if (!hwdev)
+ return 0;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ return hwif->attr.func_type;
+}
+
+u8 hifc_ppf_idx(void *hwdev)
+{
+ struct hifc_hwif *hwif;
+
+ if (!hwdev)
+ return 0;
+
+ hwif = ((struct hifc_hwdev *)hwdev)->hwif;
+
+ return hwif->attr.ppf_idx;
+}
diff --git a/drivers/scsi/huawei/hifc/hifc_hwif.h b/drivers/scsi/huawei/hifc/hifc_hwif.h
new file mode 100644
index 000000000000..da72253dcf5f
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_hwif.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_HWIF_H
+#define HIFC_HWIF_H
+
+#include "hifc_hwdev.h"
+
+#define HIFC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT 60000
+#define HIFC_CSR_GLOBAL_BASE_ADDR 0x4000
+/* HW interface registers */
+#define HIFC_CSR_FUNC_ATTR0_ADDR 0x0
+#define HIFC_CSR_FUNC_ATTR1_ADDR 0x4
+#define HIFC_CSR_FUNC_ATTR2_ADDR 0x8
+#define HIFC_CSR_FUNC_ATTR4_ADDR 0x10
+
+#define HIFC_CSR_FUNC_ATTR5_ADDR 0x14
+#define HIFC_PCI_MSIX_ENTRY_SIZE 16
+#define HIFC_PCI_MSIX_ENTRY_VECTOR_CTRL 12
+#define HIFC_PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+
+/* total doorbell or direct wqe size is 512kB, db num: 128, dwqe: 128*/
+#define HIFC_DB_DWQE_SIZE 0x00080000
+/* db/dwqe page size: 4K */
+#define HIFC_DB_PAGE_SIZE 0x00001000ULL
+#define HIFC_DB_MAX_AREAS (HIFC_DB_DWQE_SIZE / HIFC_DB_PAGE_SIZE)
+
+#define HIFC_ELECTION_BASE 0x200
+#define HIFC_PPF_ELECTION_STRIDE 0x4
+#define HIFC_CSR_MAX_PORTS 4
+#define HIFC_CSR_PPF_ELECTION_ADDR \
+ (HIFC_CSR_GLOBAL_BASE_ADDR + HIFC_ELECTION_BASE)
+
+#define HIFC_CSR_GLOBAL_MPF_ELECTION_ADDR \
+ (HIFC_CSR_GLOBAL_BASE_ADDR + HIFC_ELECTION_BASE + \
+ HIFC_CSR_MAX_PORTS * HIFC_PPF_ELECTION_STRIDE)
+#define DB_IDX(db, db_base) \
+ ((u32)(((ulong)(db) - (ulong)(db_base)) / \
+ HIFC_DB_PAGE_SIZE))
+
+#define HIFC_AF0_FUNC_GLOBAL_IDX_SHIFT 0
+#define HIFC_AF0_P2P_IDX_SHIFT 10
+#define HIFC_AF0_PCI_INTF_IDX_SHIFT 14
+#define HIFC_AF0_VF_IN_PF_SHIFT 16
+#define HIFC_AF0_FUNC_TYPE_SHIFT 24
+#define HIFC_AF0_FUNC_GLOBAL_IDX_MASK 0x3FF
+#define HIFC_AF0_P2P_IDX_MASK 0xF
+#define HIFC_AF0_PCI_INTF_IDX_MASK 0x3
+#define HIFC_AF0_VF_IN_PF_MASK 0xFF
+#define HIFC_AF0_FUNC_TYPE_MASK 0x1
+
+#define HIFC_AF0_GET(val, member) \
+ (((val) >> HIFC_AF0_##member##_SHIFT) & HIFC_AF0_##member##_MASK)
+
+#define HIFC_AF1_PPF_IDX_SHIFT 0
+#define HIFC_AF1_AEQS_PER_FUNC_SHIFT 8
+#define HIFC_AF1_CEQS_PER_FUNC_SHIFT 12
+#define HIFC_AF1_IRQS_PER_FUNC_SHIFT 20
+#define HIFC_AF1_DMA_ATTR_PER_FUNC_SHIFT 24
+#define HIFC_AF1_MGMT_INIT_STATUS_SHIFT 30
+#define HIFC_AF1_PF_INIT_STATUS_SHIFT 31
+
+#define HIFC_AF1_PPF_IDX_MASK 0x1F
+#define HIFC_AF1_AEQS_PER_FUNC_MASK 0x3
+#define HIFC_AF1_CEQS_PER_FUNC_MASK 0x7
+#define HIFC_AF1_IRQS_PER_FUNC_MASK 0xF
+#define HIFC_AF1_DMA_ATTR_PER_FUNC_MASK 0x7
+#define HIFC_AF1_MGMT_INIT_STATUS_MASK 0x1
+#define HIFC_AF1_PF_INIT_STATUS_MASK 0x1
+
+#define HIFC_AF1_GET(val, member) \
+ (((val) >> HIFC_AF1_##member##_SHIFT) & HIFC_AF1_##member##_MASK)
+
+#define HIFC_AF4_OUTBOUND_CTRL_SHIFT 0
+#define HIFC_AF4_DOORBELL_CTRL_SHIFT 1
+#define HIFC_AF4_OUTBOUND_CTRL_MASK 0x1
+#define HIFC_AF4_DOORBELL_CTRL_MASK 0x1
+
+#define HIFC_AF4_GET(val, member) \
+ (((val) >> HIFC_AF4_##member##_SHIFT) & HIFC_AF4_##member##_MASK)
+
+#define HIFC_AF4_SET(val, member) \
+ (((val) & HIFC_AF4_##member##_MASK) << HIFC_AF4_##member##_SHIFT)
+
+#define HIFC_AF4_CLEAR(val, member) \
+ ((val) & (~(HIFC_AF4_##member##_MASK << \
+ HIFC_AF4_##member##_SHIFT)))
+
+#define HIFC_AF5_PF_STATUS_SHIFT 0
+#define HIFC_AF5_PF_STATUS_MASK 0xFFFF
+
+#define HIFC_AF5_SET(val, member) \
+ (((val) & HIFC_AF5_##member##_MASK) << HIFC_AF5_##member##_SHIFT)
+
+#define HIFC_AF5_GET(val, member) \
+ (((val) >> HIFC_AF5_##member##_SHIFT) & HIFC_AF5_##member##_MASK)
+
+#define HIFC_PPF_ELECTION_IDX_SHIFT 0
+#define HIFC_PPF_ELECTION_IDX_MASK 0x1F
+
+#define HIFC_PPF_ELECTION_SET(val, member) \
+ (((val) & HIFC_PPF_ELECTION_##member##_MASK) << \
+ HIFC_PPF_ELECTION_##member##_SHIFT)
+
+#define HIFC_PPF_ELECTION_GET(val, member) \
+ (((val) >> HIFC_PPF_ELECTION_##member##_SHIFT) & \
+ HIFC_PPF_ELECTION_##member##_MASK)
+
+#define HIFC_PPF_ELECTION_CLEAR(val, member) \
+ ((val) & (~(HIFC_PPF_ELECTION_##member##_MASK \
+ << HIFC_PPF_ELECTION_##member##_SHIFT)))
+
+#define HIFC_MPF_ELECTION_IDX_SHIFT 0
+#define HIFC_MPF_ELECTION_IDX_MASK 0x1F
+
+#define HIFC_MPF_ELECTION_SET(val, member) \
+ (((val) & HIFC_MPF_ELECTION_##member##_MASK) << \
+ HIFC_MPF_ELECTION_##member##_SHIFT)
+
+#define HIFC_MPF_ELECTION_GET(val, member) \
+ (((val) >> HIFC_MPF_ELECTION_##member##_SHIFT) & \
+ HIFC_MPF_ELECTION_##member##_MASK)
+
+#define HIFC_MPF_ELECTION_CLEAR(val, member) \
+ ((val) & (~(HIFC_MPF_ELECTION_##member##_MASK \
+ << HIFC_MPF_ELECTION_##member##_SHIFT)))
+
+#define HIFC_HWIF_NUM_AEQS(hwif) ((hwif)->attr.num_aeqs)
+#define HIFC_HWIF_NUM_CEQS(hwif) ((hwif)->attr.num_ceqs)
+#define HIFC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx)
+#define HIFC_PCI_INTF_IDX(hwif) ((hwif)->attr.pci_intf_idx)
+
+#define HIFC_FUNC_TYPE(dev) ((dev)->hwif->attr.func_type)
+#define HIFC_IS_PPF(dev) (HIFC_FUNC_TYPE(dev) == TYPE_PPF)
+
+enum hifc_pcie_nosnoop {
+ HIFC_PCIE_SNOOP = 0,
+ HIFC_PCIE_NO_SNOOP = 1,
+};
+
+enum hifc_pcie_tph {
+ HIFC_PCIE_TPH_DISABLE = 0,
+ HIFC_PCIE_TPH_ENABLE = 1,
+};
+
+enum hifc_pf_status {
+ HIFC_PF_STATUS_INIT = 0X0,
+ HIFC_PF_STATUS_ACTIVE_FLAG = 0x11,
+ HIFC_PF_STATUS_FLR_START_FLAG = 0x12,
+ HIFC_PF_STATUS_FLR_FINISH_FLAG = 0x13,
+};
+
+enum hifc_outbound_ctrl {
+ ENABLE_OUTBOUND = 0x0,
+ DISABLE_OUTBOUND = 0x1,
+};
+
+enum hifc_doorbell_ctrl {
+ ENABLE_DOORBELL = 0x0,
+ DISABLE_DOORBELL = 0x1,
+};
+
+struct hifc_free_db_area {
+ u32 db_idx[HIFC_DB_MAX_AREAS];
+ u32 num_free;
+ u32 alloc_pos;
+ u32 return_pos;
+ /* spinlock for allocating doorbell area */
+ spinlock_t idx_lock;
+};
+
+enum func_type {
+ TYPE_PF,
+ TYPE_VF,
+ TYPE_PPF,
+ TYPE_UNKNOWN,
+};
+
+struct hifc_func_attr {
+ u16 func_global_idx;
+ u8 port_to_port_idx;
+ u8 pci_intf_idx;
+ u8 vf_in_pf;
+ enum func_type func_type;
+
+ u8 mpf_idx;
+
+ u8 ppf_idx;
+
+ u16 num_irqs; /* max: 2 ^ 15 */
+ u8 num_aeqs; /* max: 2 ^ 3 */
+ u8 num_ceqs; /* max: 2 ^ 7 */
+
+ u8 num_dma_attr; /* max: 2 ^ 6 */
+};
+
+struct hifc_hwif {
+ u8 __iomem *cfg_regs_base;
+ u8 __iomem *intr_regs_base;
+ u64 db_base_phy;
+ u8 __iomem *db_base;
+
+#if defined(__aarch64__)
+ void __iomem *dwqe_mapping;
+#else
+ struct io_mapping *dwqe_mapping;
+#endif
+ struct hifc_free_db_area free_db_area;
+ struct hifc_func_attr attr;
+ void *pdev;
+};
+
+struct hifc_dma_addr_align {
+ u32 real_size;
+ void *ori_vaddr;
+ dma_addr_t ori_paddr;
+ void *align_vaddr;
+ dma_addr_t align_paddr;
+};
+
+u32 hifc_hwif_read_reg(struct hifc_hwif *hwif, u32 reg);
+void hifc_hwif_write_reg(struct hifc_hwif *hwif, u32 reg, u32 val);
+void hifc_set_pf_status(struct hifc_hwif *hwif, enum hifc_pf_status status);
+enum hifc_pf_status hifc_get_pf_status(struct hifc_hwif *hwif);
+enum hifc_doorbell_ctrl
+ hifc_get_doorbell_ctrl_status(struct hifc_hwif *hwif);
+enum hifc_outbound_ctrl
+ hifc_get_outbound_ctrl_status(struct hifc_hwif *hwif);
+void hifc_enable_doorbell(struct hifc_hwif *hwif);
+void hifc_disable_doorbell(struct hifc_hwif *hwif);
+int hifc_init_hwif(struct hifc_hwdev *hwdev, void *cfg_reg_base,
+ void *intr_reg_base, u64 db_base_phy,
+ void *db_base, void *dwqe_mapping);
+void hifc_free_hwif(struct hifc_hwdev *hwdev);
+int hifc_dma_zalloc_coherent_align(void *dev_hdl, u64 size, u64 align,
+ unsigned flag,
+ struct hifc_dma_addr_align *mem_align);
+void hifc_dma_free_coherent_align(void *dev_hdl,
+ struct hifc_dma_addr_align *mem_align);
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_mgmt.c b/drivers/scsi/huawei/hifc/hifc_mgmt.c
new file mode 100644
index 000000000000..3f4818898e8d
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_mgmt.c
@@ -0,0 +1,1426 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_hwif.h"
+#include "hifc_api_cmd.h"
+#include "hifc_mgmt.h"
+#include "hifc_eqs.h"
+
+#define BUF_OUT_DEFAULT_SIZE 1
+#define SEGMENT_LEN 48
+#define MGMT_MSG_MAX_SEQ_ID (ALIGN(HIFC_MSG_TO_MGMT_MAX_LEN, \
+ SEGMENT_LEN) / SEGMENT_LEN)
+
+#define MAX_PF_MGMT_BUF_SIZE 2048UL
+#define MGMT_MSG_SIZE_MIN 20
+#define MGMT_MSG_SIZE_STEP 16
+#define MGMT_MSG_RSVD_FOR_DEV 8
+#define MGMT_MSG_TIMEOUT 5000 /* millisecond */
+#define SYNC_MSG_ID_MASK 0x1FF
+#define ASYNC_MSG_ID_MASK 0x1FF
+#define ASYNC_MSG_FLAG 0x200
+#define MSG_NO_RESP 0xFFFF
+#define MAX_MSG_SZ 2016
+
+#define MSG_SZ_IS_VALID(in_size) ((in_size) <= MAX_MSG_SZ)
+
+#define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id)
+
+#define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \
+ (SYNC_MSG_ID(pf_to_mgmt) + 1) & SYNC_MSG_ID_MASK)
+
+#define ASYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->async_msg_id)
+
+#define ASYNC_MSG_ID_INC(pf_to_mgmt) (ASYNC_MSG_ID(pf_to_mgmt) = \
+ ((ASYNC_MSG_ID(pf_to_mgmt) + 1) & ASYNC_MSG_ID_MASK) \
+ | ASYNC_MSG_FLAG)
+
+static void pf_to_mgmt_send_event_set(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ int event_flag)
+{
+ spin_lock(&pf_to_mgmt->sync_event_lock);
+ pf_to_mgmt->event_flag = event_flag;
+ spin_unlock(&pf_to_mgmt->sync_event_lock);
+}
+
+/**
+ * hifc_register_mgmt_msg_cb - register sync msg handler for a module
+ * @hwdev: the pointer to hw device
+ * @mod: module in the chip that this handler will handle its sync messages
+ * @pri_handle: pri handle function
+ * @callback: the handler for a sync message that will handle messages
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_register_mgmt_msg_cb(void *hwdev, enum hifc_mod_type mod,
+ void *pri_handle, hifc_mgmt_msg_cb callback)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+
+ if (mod >= HIFC_MOD_HW_MAX || !hwdev)
+ return -EFAULT;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+ if (!pf_to_mgmt)
+ return -EINVAL;
+
+ pf_to_mgmt->recv_mgmt_msg_cb[mod] = callback;
+ pf_to_mgmt->recv_mgmt_msg_data[mod] = pri_handle;
+
+ set_bit(HIFC_MGMT_MSG_CB_REG, &pf_to_mgmt->mgmt_msg_cb_state[mod]);
+
+ return 0;
+}
+
+/**
+ * hifc_unregister_mgmt_msg_cb - unregister sync msg handler for a module
+ * @hwdev: the pointer to hw device
+ * @mod: module in the chip that this handler will handle its sync messages
+ **/
+void hifc_unregister_mgmt_msg_cb(void *hwdev, enum hifc_mod_type mod)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+
+ if (!hwdev || mod >= HIFC_MOD_HW_MAX)
+ return;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+ if (!pf_to_mgmt)
+ return;
+
+ clear_bit(HIFC_MGMT_MSG_CB_REG, &pf_to_mgmt->mgmt_msg_cb_state[mod]);
+
+ while (test_bit(HIFC_MGMT_MSG_CB_RUNNING,
+ &pf_to_mgmt->mgmt_msg_cb_state[mod]))
+ usleep_range(900, 1000);
+
+ pf_to_mgmt->recv_mgmt_msg_cb[mod] = NULL;
+ pf_to_mgmt->recv_mgmt_msg_data[mod] = NULL;
+}
+
+void hifc_comm_recv_mgmt_self_cmd_reg(void *hwdev, u8 cmd,
+ comm_up_self_msg_proc proc)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ u8 cmd_idx;
+
+ if (!hwdev || !proc)
+ return;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+ if (!pf_to_mgmt)
+ return;
+
+ cmd_idx = pf_to_mgmt->proc.cmd_num;
+ if (cmd_idx >= HIFC_COMM_SELF_CMD_MAX) {
+ sdk_err(pf_to_mgmt->hwdev->dev_hdl,
+ "Register recv up process failed(cmd=0x%x)\r\n", cmd);
+ return;
+ }
+
+ pf_to_mgmt->proc.info[cmd_idx].cmd = cmd;
+ pf_to_mgmt->proc.info[cmd_idx].proc = proc;
+
+ pf_to_mgmt->proc.cmd_num++;
+}
+
+void hifc_comm_recv_up_self_cmd_unreg(void *hwdev, u8 cmd)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ u8 cmd_idx;
+
+ if (!hwdev)
+ return;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+ if (!pf_to_mgmt)
+ return;
+
+ cmd_idx = pf_to_mgmt->proc.cmd_num;
+ if (cmd_idx >= HIFC_COMM_SELF_CMD_MAX) {
+ sdk_err(pf_to_mgmt->hwdev->dev_hdl,
+ "Unregister recv up process failed(cmd=0x%x)\r\n", cmd);
+ return;
+ }
+
+ for (cmd_idx = 0; cmd_idx < HIFC_COMM_SELF_CMD_MAX; cmd_idx++) {
+ if (cmd == pf_to_mgmt->proc.info[cmd_idx].cmd) {
+ pf_to_mgmt->proc.info[cmd_idx].cmd = 0;
+ pf_to_mgmt->proc.info[cmd_idx].proc = NULL;
+ pf_to_mgmt->proc.cmd_num--;
+ }
+ }
+}
+
+/**
+ * mgmt_msg_len - calculate the total message length
+ * @msg_data_len: the length of the message data
+ * Return: the total message length
+ **/
+static u16 mgmt_msg_len(u16 msg_data_len)
+{
+ /* u64 - the size of the header */
+ u16 msg_size;
+
+ msg_size = (u16)(MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len);
+
+ if (msg_size > MGMT_MSG_SIZE_MIN)
+ msg_size = MGMT_MSG_SIZE_MIN +
+ ALIGN((msg_size - MGMT_MSG_SIZE_MIN),
+ MGMT_MSG_SIZE_STEP);
+ else
+ msg_size = MGMT_MSG_SIZE_MIN;
+
+ return msg_size;
+}
+
+/**
+ * prepare_header - prepare the header of the message
+ * @pf_to_mgmt: PF to MGMT channel
+ * @header: pointer of the header to prepare
+ * @msg_len: the length of the message
+ * @mod: module in the chip that will get the message
+ * @ack_type: message ack type
+ * @direction: the direction of the original message
+ * @cmd: vmd type
+ * @msg_id: message id
+ **/
+static void prepare_header(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ u64 *header, u16 msg_len, enum hifc_mod_type mod,
+ enum hifc_msg_ack_type ack_type,
+ enum hifc_msg_direction_type direction,
+ enum hifc_mgmt_cmd cmd, u32 msg_id)
+{
+ struct hifc_hwif *hwif = pf_to_mgmt->hwdev->hwif;
+
+ *header = HIFC_MSG_HEADER_SET(msg_len, MSG_LEN) |
+ HIFC_MSG_HEADER_SET(mod, MODULE) |
+ HIFC_MSG_HEADER_SET(msg_len, SEG_LEN) |
+ HIFC_MSG_HEADER_SET(ack_type, NO_ACK) |
+ HIFC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) |
+ HIFC_MSG_HEADER_SET(0, SEQID) |
+ HIFC_MSG_HEADER_SET(LAST_SEGMENT, LAST) |
+ HIFC_MSG_HEADER_SET(direction, DIRECTION) |
+ HIFC_MSG_HEADER_SET(cmd, CMD) |
+ HIFC_MSG_HEADER_SET(HIFC_PCI_INTF_IDX(hwif), PCI_INTF_IDX) |
+ HIFC_MSG_HEADER_SET(hwif->attr.port_to_port_idx, P2P_IDX) |
+ HIFC_MSG_HEADER_SET(msg_id, MSG_ID);
+}
+
+static void clp_prepare_header(struct hifc_hwdev *hwdev,
+ u64 *header, u16 msg_len, enum hifc_mod_type mod,
+ enum hifc_msg_ack_type ack_type,
+ enum hifc_msg_direction_type direction,
+ enum hifc_mgmt_cmd cmd, u32 msg_id)
+{
+ struct hifc_hwif *hwif = hwdev->hwif;
+
+ *header = HIFC_MSG_HEADER_SET(msg_len, MSG_LEN) |
+ HIFC_MSG_HEADER_SET(mod, MODULE) |
+ HIFC_MSG_HEADER_SET(msg_len, SEG_LEN) |
+ HIFC_MSG_HEADER_SET(ack_type, NO_ACK) |
+ HIFC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) |
+ HIFC_MSG_HEADER_SET(0, SEQID) |
+ HIFC_MSG_HEADER_SET(LAST_SEGMENT, LAST) |
+ HIFC_MSG_HEADER_SET(direction, DIRECTION) |
+ HIFC_MSG_HEADER_SET(cmd, CMD) |
+ HIFC_MSG_HEADER_SET(HIFC_PCI_INTF_IDX(hwif), PCI_INTF_IDX) |
+ HIFC_MSG_HEADER_SET(hwif->attr.port_to_port_idx, P2P_IDX) |
+ HIFC_MSG_HEADER_SET(msg_id, MSG_ID);
+}
+
+/**
+ * prepare_mgmt_cmd - prepare the mgmt command
+ * @mgmt_cmd: pointer to the command to prepare
+ * @header: pointer of the header to prepare
+ * @msg: the data of the message
+ * @msg_len: the length of the message
+ **/
+static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, const void *msg,
+ int msg_len)
+{
+ memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
+
+ mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;
+ memcpy(mgmt_cmd, header, sizeof(*header));
+
+ mgmt_cmd += sizeof(*header);
+ memcpy(mgmt_cmd, msg, msg_len);
+}
+
+/**
+ * send_msg_to_mgmt_async - send async message
+ * @pf_to_mgmt: PF to MGMT channel
+ * @mod: module in the chip that will get the message
+ * @cmd: command of the message
+ * @msg: the data of the message
+ * @msg_len: the length of the message
+ * @direction: the direction of the original message
+ * @resp_msg_id: msg id to response for
+ * Return: 0 - success, negative - failure
+ **/
+static int send_msg_to_mgmt_async(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ enum hifc_mod_type mod, u8 cmd,
+ void *msg, u16 msg_len,
+ enum hifc_msg_direction_type direction,
+ u16 resp_msg_id)
+{
+ void *mgmt_cmd = pf_to_mgmt->async_msg_buf;
+ struct hifc_api_cmd_chain *chain;
+ u64 header;
+ u16 cmd_size = mgmt_msg_len(msg_len);
+
+ if (!hifc_get_chip_present_flag(pf_to_mgmt->hwdev))
+ return -EFAULT;
+
+ if (direction == HIFC_MSG_RESPONSE)
+ prepare_header(pf_to_mgmt, &header, msg_len, mod, HIFC_MSG_ACK,
+ direction, cmd, resp_msg_id);
+ else
+ prepare_header(pf_to_mgmt, &header, msg_len, mod, HIFC_MSG_ACK,
+ direction, cmd, ASYNC_MSG_ID(pf_to_mgmt));
+
+ prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len);
+
+ chain = pf_to_mgmt->cmd_chain[HIFC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU];
+
+ return hifc_api_cmd_write(chain, HIFC_NODE_ID_MGMT_HOST, mgmt_cmd,
+ cmd_size);
+}
+
+int hifc_pf_to_mgmt_async(void *hwdev, enum hifc_mod_type mod,
+ u8 cmd, void *buf_in, u16 in_size)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ void *dev = ((struct hifc_hwdev *)hwdev)->dev_hdl;
+ int err;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+
+ /* Lock the async_msg_buf */
+ spin_lock_bh(&pf_to_mgmt->async_msg_lock);
+ ASYNC_MSG_ID_INC(pf_to_mgmt);
+
+ err = send_msg_to_mgmt_async(pf_to_mgmt, mod, cmd, buf_in, in_size,
+ HIFC_MSG_DIRECT_SEND, MSG_NO_RESP);
+ spin_unlock_bh(&pf_to_mgmt->async_msg_lock);
+
+ if (err) {
+ sdk_err(dev, "Failed to send async mgmt msg\n");
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * send_msg_to_mgmt_sync - send async message
+ * @pf_to_mgmt: PF to MGMT channel
+ * @mod: module in the chip that will get the message
+ * @cmd: command of the message
+ * @msg: the msg data
+ * @msg_len: the msg data length
+ * @direction: the direction of the original message
+ * @resp_msg_id: msg id to response for
+ * Return: 0 - success, negative - failure
+ **/
+static int send_msg_to_mgmt_sync(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ enum hifc_mod_type mod, u8 cmd,
+ void *msg, u16 msg_len,
+ enum hifc_msg_ack_type ack_type,
+ enum hifc_msg_direction_type direction,
+ u16 resp_msg_id)
+{
+ void *mgmt_cmd = pf_to_mgmt->sync_msg_buf;
+ struct hifc_api_cmd_chain *chain;
+ u64 header;
+ u16 cmd_size = mgmt_msg_len(msg_len);
+
+ if (!hifc_get_chip_present_flag(pf_to_mgmt->hwdev))
+ return -EFAULT;
+
+ if (direction == HIFC_MSG_RESPONSE)
+ prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
+ direction, cmd, resp_msg_id);
+ else
+ prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
+ direction, cmd, SYNC_MSG_ID_INC(pf_to_mgmt));
+
+ if (ack_type == HIFC_MSG_ACK)
+ pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_START);
+
+ prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len);
+
+ chain = pf_to_mgmt->cmd_chain[HIFC_API_CMD_WRITE_TO_MGMT_CPU];
+
+ return hifc_api_cmd_write(chain, HIFC_NODE_ID_MGMT_HOST, mgmt_cmd,
+ cmd_size);
+}
+
+static inline void msg_to_mgmt_pre(enum hifc_mod_type mod, void *buf_in)
+{
+ struct hifc_msg_head *msg_head;
+
+ /* set aeq fix num to 3, need to ensure response aeq id < 3*/
+ if (mod == HIFC_MOD_COMM || mod == HIFC_MOD_L2NIC) {
+ msg_head = buf_in;
+
+ if (msg_head->resp_aeq_num >= HIFC_MAX_AEQS)
+ msg_head->resp_aeq_num = 0;
+ }
+}
+
+int hifc_pf_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size, void *buf_out,
+ u16 *out_size, u32 timeout)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ void *dev = ((struct hifc_hwdev *)hwdev)->dev_hdl;
+ struct hifc_recv_msg *recv_msg;
+ struct completion *recv_done;
+ ulong timeo;
+ int err;
+ ulong ret;
+
+ msg_to_mgmt_pre(mod, buf_in);
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+
+ /* Lock the sync_msg_buf */
+ down(&pf_to_mgmt->sync_msg_lock);
+ recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
+ recv_done = &recv_msg->recv_done;
+
+ init_completion(recv_done);
+
+ err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
+ HIFC_MSG_ACK, HIFC_MSG_DIRECT_SEND,
+ MSG_NO_RESP);
+ if (err) {
+ sdk_err(dev, "Failed to send sync msg to mgmt, sync_msg_id: %d\n",
+ pf_to_mgmt->sync_msg_id);
+ pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_FAIL);
+ goto unlock_sync_msg;
+ }
+
+ timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
+
+ ret = wait_for_completion_timeout(recv_done, timeo);
+ if (!ret) {
+ sdk_err(dev, "Mgmt response sync cmd timeout, sync_msg_id: %d\n",
+ pf_to_mgmt->sync_msg_id);
+ hifc_dump_aeq_info((struct hifc_hwdev *)hwdev);
+ err = -ETIMEDOUT;
+ pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_TIMEOUT);
+ goto unlock_sync_msg;
+ }
+ pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_END);
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag)) {
+ up(&pf_to_mgmt->sync_msg_lock);
+ return -ETIMEDOUT;
+ }
+
+ if (buf_out && out_size) {
+ if (*out_size < recv_msg->msg_len) {
+ sdk_err(dev, "Invalid response message length: %d for mod %d cmd %d from mgmt, should less than: %d\n",
+ recv_msg->msg_len, mod, cmd, *out_size);
+ err = -EFAULT;
+ goto unlock_sync_msg;
+ }
+
+ if (recv_msg->msg_len)
+ memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);
+
+ *out_size = recv_msg->msg_len;
+ }
+
+unlock_sync_msg:
+ up(&pf_to_mgmt->sync_msg_lock);
+
+ return err;
+}
+
+static int __get_clp_reg(void *hwdev, enum clp_data_type data_type,
+ enum clp_reg_type reg_type, u32 *reg_addr)
+{
+ struct hifc_hwdev *dev = hwdev;
+ u32 offset;
+
+ offset = HIFC_CLP_REG_GAP * hifc_pcie_itf_id(dev);
+
+ switch (reg_type) {
+ case HIFC_CLP_BA_HOST:
+ *reg_addr = (data_type == HIFC_CLP_REQ_HOST) ?
+ HIFC_CLP_REG(REQ_SRAM_BA) :
+ HIFC_CLP_REG(RSP_SRAM_BA);
+ break;
+
+ case HIFC_CLP_SIZE_HOST:
+ *reg_addr = HIFC_CLP_REG(SRAM_SIZE);
+ break;
+
+ case HIFC_CLP_LEN_HOST:
+ *reg_addr = (data_type == HIFC_CLP_REQ_HOST) ?
+ HIFC_CLP_REG(REQ) : HIFC_CLP_REG(RSP);
+ break;
+
+ case HIFC_CLP_START_REQ_HOST:
+ *reg_addr = HIFC_CLP_REG(REQ);
+ break;
+
+ case HIFC_CLP_READY_RSP_HOST:
+ *reg_addr = HIFC_CLP_REG(RSP);
+ break;
+
+ default:
+ *reg_addr = 0;
+ break;
+ }
+ if (*reg_addr == 0)
+ return -EINVAL;
+
+ *reg_addr += offset;
+
+ return 0;
+}
+
+static inline int clp_param_valid(struct hifc_hwdev *hwdev,
+ enum clp_data_type data_type,
+ enum clp_reg_type reg_type)
+{
+ if (data_type == HIFC_CLP_REQ_HOST &&
+ reg_type == HIFC_CLP_READY_RSP_HOST)
+ return -EINVAL;
+
+ if (data_type == HIFC_CLP_RSP_HOST &&
+ reg_type == HIFC_CLP_START_REQ_HOST)
+ return -EINVAL;
+
+ return 0;
+}
+
+static u32 get_clp_reg_value(struct hifc_hwdev *hwdev,
+ enum clp_reg_type reg_type, u32 reg_addr)
+{
+ u32 reg_value;
+
+ reg_value = hifc_hwif_read_reg(hwdev->hwif, reg_addr);
+
+ switch (reg_type) {
+ case HIFC_CLP_BA_HOST:
+ reg_value = ((reg_value >>
+ HIFC_CLP_OFFSET(SRAM_BASE)) &
+ HIFC_CLP_MASK(SRAM_BASE));
+ break;
+
+ case HIFC_CLP_SIZE_HOST:
+ reg_value = ((reg_value >>
+ HIFC_CLP_OFFSET(SRAM_SIZE)) &
+ HIFC_CLP_MASK(SRAM_SIZE));
+ break;
+
+ case HIFC_CLP_LEN_HOST:
+ reg_value = ((reg_value >> HIFC_CLP_OFFSET(LEN)) &
+ HIFC_CLP_MASK(LEN));
+ break;
+
+ case HIFC_CLP_START_REQ_HOST:
+ reg_value = ((reg_value >> HIFC_CLP_OFFSET(START)) &
+ HIFC_CLP_MASK(START));
+ break;
+
+ case HIFC_CLP_READY_RSP_HOST:
+ reg_value = ((reg_value >> HIFC_CLP_OFFSET(READY)) &
+ HIFC_CLP_MASK(READY));
+ break;
+
+ default:
+ break;
+ }
+
+ return reg_value;
+}
+
+static int hifc_read_clp_reg(struct hifc_hwdev *hwdev,
+ enum clp_data_type data_type,
+ enum clp_reg_type reg_type, u32 *read_value)
+{
+ u32 reg_addr;
+ int err;
+
+ err = clp_param_valid(hwdev, data_type, reg_type);
+ if (err)
+ return err;
+
+ err = __get_clp_reg(hwdev, data_type, reg_type, ®_addr);
+ if (err)
+ return err;
+
+ *read_value = get_clp_reg_value(hwdev, reg_type, reg_addr);
+
+ return 0;
+}
+
+static int __check_data_type(enum clp_data_type data_type,
+ enum clp_reg_type reg_type)
+{
+ if (data_type == HIFC_CLP_REQ_HOST &&
+ reg_type == HIFC_CLP_READY_RSP_HOST)
+ return -EINVAL;
+ if (data_type == HIFC_CLP_RSP_HOST &&
+ reg_type == HIFC_CLP_START_REQ_HOST)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int __check_reg_value(enum clp_reg_type reg_type, u32 value)
+{
+ if (reg_type == HIFC_CLP_BA_HOST &&
+ value > HIFC_CLP_SRAM_BASE_REG_MAX)
+ return -EINVAL;
+
+ if (reg_type == HIFC_CLP_SIZE_HOST &&
+ value > HIFC_CLP_SRAM_SIZE_REG_MAX)
+ return -EINVAL;
+
+ if (reg_type == HIFC_CLP_LEN_HOST &&
+ value > HIFC_CLP_LEN_REG_MAX)
+ return -EINVAL;
+
+ if ((reg_type == HIFC_CLP_START_REQ_HOST ||
+ reg_type == HIFC_CLP_READY_RSP_HOST) &&
+ value > HIFC_CLP_START_OR_READY_REG_MAX)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void hifc_write_clp_reg(struct hifc_hwdev *hwdev,
+ enum clp_data_type data_type,
+ enum clp_reg_type reg_type, u32 value)
+{
+ u32 reg_addr, reg_value;
+
+ if (__check_data_type(data_type, reg_type))
+ return;
+
+ if (__check_reg_value(reg_type, value))
+ return;
+
+ if (__get_clp_reg(hwdev, data_type, reg_type, ®_addr))
+ return;
+
+ reg_value = hifc_hwif_read_reg(hwdev->hwif, reg_addr);
+
+ switch (reg_type) {
+ case HIFC_CLP_LEN_HOST:
+ reg_value = reg_value &
+ (~(HIFC_CLP_MASK(LEN) << HIFC_CLP_OFFSET(LEN)));
+ reg_value = reg_value | (value << HIFC_CLP_OFFSET(LEN));
+ break;
+
+ case HIFC_CLP_START_REQ_HOST:
+ reg_value = reg_value &
+ (~(HIFC_CLP_MASK(START) <<
+ HIFC_CLP_OFFSET(START)));
+ reg_value = reg_value | (value << HIFC_CLP_OFFSET(START));
+ break;
+
+ case HIFC_CLP_READY_RSP_HOST:
+ reg_value = reg_value &
+ (~(HIFC_CLP_MASK(READY) <<
+ HIFC_CLP_OFFSET(READY)));
+ reg_value = reg_value | (value << HIFC_CLP_OFFSET(READY));
+ break;
+
+ default:
+ return;
+ }
+
+ hifc_hwif_write_reg(hwdev->hwif, reg_addr, reg_value);
+}
+
+static int hifc_read_clp_data(struct hifc_hwdev *hwdev,
+ void *buf_out, u16 *out_size)
+{
+ int err;
+ u32 reg = HIFC_CLP_DATA(RSP);
+ u32 ready, delay_cnt;
+ u32 *ptr = (u32 *)buf_out;
+ u32 temp_out_size = 0;
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_READY_RSP_HOST, &ready);
+ if (err)
+ return err;
+
+ delay_cnt = 0;
+ while (ready == 0) {
+ usleep_range(9000, 10000);
+ delay_cnt++;
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_READY_RSP_HOST, &ready);
+ if (err || delay_cnt > HIFC_CLP_DELAY_CNT_MAX) {
+ sdk_err(hwdev->dev_hdl, "timeout with delay_cnt:%d\n",
+ delay_cnt);
+ return -EINVAL;
+ }
+ }
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_LEN_HOST, &temp_out_size);
+ if (err)
+ return err;
+
+ if (temp_out_size > HIFC_CLP_SRAM_SIZE_REG_MAX || !temp_out_size) {
+ sdk_err(hwdev->dev_hdl, "invalid temp_out_size:%d\n",
+ temp_out_size);
+ return -EINVAL;
+ }
+
+ *out_size = (u16)(temp_out_size & 0xffff);
+ for (; temp_out_size > 0; temp_out_size--) {
+ *ptr = hifc_hwif_read_reg(hwdev->hwif, reg);
+ ptr++;
+ reg = reg + 4;
+ }
+
+ hifc_write_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_READY_RSP_HOST, (u32)0x0);
+ hifc_write_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_LEN_HOST, (u32)0x0);
+
+ return 0;
+}
+
+static int hifc_write_clp_data(struct hifc_hwdev *hwdev,
+ void *buf_in, u16 in_size)
+{
+ int err;
+ u32 reg = HIFC_CLP_DATA(REQ);
+ u32 start = 1;
+ u32 delay_cnt = 0;
+ u32 *ptr = (u32 *)buf_in;
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_REQ_HOST,
+ HIFC_CLP_START_REQ_HOST, &start);
+ if (err)
+ return err;
+
+ while (start == 1) {
+ usleep_range(9000, 10000);
+ delay_cnt++;
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_REQ_HOST,
+ HIFC_CLP_START_REQ_HOST, &start);
+ if (err || delay_cnt > HIFC_CLP_DELAY_CNT_MAX)
+ return -EINVAL;
+ }
+
+ hifc_write_clp_reg(hwdev, HIFC_CLP_REQ_HOST,
+ HIFC_CLP_LEN_HOST, in_size);
+ hifc_write_clp_reg(hwdev, HIFC_CLP_REQ_HOST,
+ HIFC_CLP_START_REQ_HOST, (u32)0x1);
+
+ for (; in_size > 0; in_size--) {
+ hifc_hwif_write_reg(hwdev->hwif, reg, *ptr);
+ ptr++;
+ reg = reg + 4;
+ }
+
+ return 0;
+}
+
+static int hifc_check_clp_init_status(struct hifc_hwdev *hwdev)
+{
+ int err;
+ u32 reg_value = 0;
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_REQ_HOST,
+ HIFC_CLP_BA_HOST, ®_value);
+ if (err || !reg_value) {
+ sdk_err(hwdev->dev_hdl, "Wrong req ba value:0x%x\n", reg_value);
+ return -EINVAL;
+ }
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_BA_HOST, ®_value);
+ if (err || !reg_value) {
+ sdk_err(hwdev->dev_hdl, "Wrong rsp ba value:0x%x\n", reg_value);
+ return -EINVAL;
+ }
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_REQ_HOST,
+ HIFC_CLP_SIZE_HOST, ®_value);
+ if (err || !reg_value) {
+ sdk_err(hwdev->dev_hdl, "Wrong req size\n");
+ return -EINVAL;
+ }
+
+ err = hifc_read_clp_reg(hwdev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_SIZE_HOST, ®_value);
+ if (err || !reg_value) {
+ sdk_err(hwdev->dev_hdl, "Wrong rsp size\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void hifc_clear_clp_data(struct hifc_hwdev *hwdev,
+ enum clp_data_type data_type)
+{
+ u32 reg = (data_type == HIFC_CLP_REQ_HOST) ?
+ HIFC_CLP_DATA(REQ) : HIFC_CLP_DATA(RSP);
+ u32 count = HIFC_CLP_INPUT_BUFFER_LEN_HOST / HIFC_CLP_DATA_UNIT_HOST;
+
+ for (; count > 0; count--) {
+ hifc_hwif_write_reg(hwdev->hwif, reg, 0x0);
+ reg = reg + 4;
+ }
+}
+
+int hifc_pf_clp_to_mgmt(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ const void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct hifc_clp_pf_to_mgmt *clp_pf_to_mgmt;
+ struct hifc_hwdev *dev = hwdev;
+ u64 header;
+ u16 real_size;
+ u8 *clp_msg_buf;
+ int err;
+
+ clp_pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->clp_pf_to_mgmt;
+ clp_msg_buf = clp_pf_to_mgmt->clp_msg_buf;
+
+ /*4 bytes alignment*/
+ if (in_size % HIFC_CLP_DATA_UNIT_HOST)
+ real_size = (in_size + (u16)sizeof(header)
+ + HIFC_CLP_DATA_UNIT_HOST);
+ else
+ real_size = in_size + (u16)sizeof(header);
+ real_size = real_size / HIFC_CLP_DATA_UNIT_HOST;
+
+ if (real_size >
+ (HIFC_CLP_INPUT_BUFFER_LEN_HOST / HIFC_CLP_DATA_UNIT_HOST)) {
+ sdk_err(dev->dev_hdl, "Invalid real_size:%d\n", real_size);
+ return -EINVAL;
+ }
+ down(&clp_pf_to_mgmt->clp_msg_lock);
+
+ err = hifc_check_clp_init_status(dev);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Check clp init status failed\n");
+ up(&clp_pf_to_mgmt->clp_msg_lock);
+ return err;
+ }
+
+ hifc_clear_clp_data(dev, HIFC_CLP_RSP_HOST);
+ hifc_write_clp_reg(dev, HIFC_CLP_RSP_HOST,
+ HIFC_CLP_READY_RSP_HOST, 0x0);
+
+ /*Send request*/
+ memset(clp_msg_buf, 0x0, HIFC_CLP_INPUT_BUFFER_LEN_HOST);
+ clp_prepare_header(dev, &header, in_size, mod, 0, 0, cmd, 0);
+
+ memcpy(clp_msg_buf, &header, sizeof(header));
+ clp_msg_buf += sizeof(header);
+ memcpy(clp_msg_buf, buf_in, in_size);
+
+ clp_msg_buf = clp_pf_to_mgmt->clp_msg_buf;
+
+ hifc_clear_clp_data(dev, HIFC_CLP_REQ_HOST);
+ err = hifc_write_clp_data(hwdev,
+ clp_pf_to_mgmt->clp_msg_buf, real_size);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Send clp request failed\n");
+ up(&clp_pf_to_mgmt->clp_msg_lock);
+ return -EINVAL;
+ }
+
+ /*Get response*/
+ clp_msg_buf = clp_pf_to_mgmt->clp_msg_buf;
+ memset(clp_msg_buf, 0x0, HIFC_CLP_INPUT_BUFFER_LEN_HOST);
+ err = hifc_read_clp_data(hwdev, clp_msg_buf, &real_size);
+ hifc_clear_clp_data(dev, HIFC_CLP_RSP_HOST);
+ if (err) {
+ sdk_err(dev->dev_hdl, "Read clp response failed\n");
+ up(&clp_pf_to_mgmt->clp_msg_lock);
+ return -EINVAL;
+ }
+
+ real_size = (u16)((real_size * HIFC_CLP_DATA_UNIT_HOST) & 0xffff);
+ if ((real_size <= sizeof(header)) ||
+ (real_size > HIFC_CLP_INPUT_BUFFER_LEN_HOST)) {
+ sdk_err(dev->dev_hdl, "Invalid response size:%d", real_size);
+ up(&clp_pf_to_mgmt->clp_msg_lock);
+ return -EINVAL;
+ }
+ real_size = real_size - sizeof(header);
+ if (real_size != *out_size) {
+ sdk_err(dev->dev_hdl, "Invalid real_size:%d, out_size:%d\n",
+ real_size, *out_size);
+ up(&clp_pf_to_mgmt->clp_msg_lock);
+ return -EINVAL;
+ }
+
+ memcpy(buf_out, (clp_msg_buf + sizeof(header)), real_size);
+ up(&clp_pf_to_mgmt->clp_msg_lock);
+
+ return 0;
+}
+
+/* This function is only used by txrx flush */
+int hifc_pf_to_mgmt_no_ack(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ void *dev = ((struct hifc_hwdev *)hwdev)->dev_hdl;
+ int err = -EINVAL;
+
+ if (!hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED)) {
+ sdk_err(dev, "Mgmt module not initialized\n");
+ return -EINVAL;
+ }
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+
+ if (!MSG_SZ_IS_VALID(in_size)) {
+ sdk_err(dev, "Mgmt msg buffer size: %d is not valid\n",
+ in_size);
+ return -EINVAL;
+ }
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag))
+ return -EPERM;
+
+ /* Lock the sync_msg_buf */
+ down(&pf_to_mgmt->sync_msg_lock);
+
+ err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
+ HIFC_MSG_NO_ACK, HIFC_MSG_DIRECT_SEND,
+ MSG_NO_RESP);
+
+ up(&pf_to_mgmt->sync_msg_lock);
+
+ return err;
+}
+
+/**
+ * api cmd write or read bypass defaut use poll, if want to use aeq interrupt,
+ * please set wb_trigger_aeqe to 1
+ **/
+int hifc_api_cmd_write_nack(void *hwdev, u8 dest, void *cmd, u16 size)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ struct hifc_api_cmd_chain *chain;
+
+ if (!hwdev || !size || !cmd)
+ return -EINVAL;
+
+ if (!hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED) ||
+ hifc_get_mgmt_channel_status(hwdev))
+ return -EPERM;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+ chain = pf_to_mgmt->cmd_chain[HIFC_API_CMD_POLL_WRITE];
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag))
+ return -EPERM;
+
+ return hifc_api_cmd_write(chain, dest, cmd, size);
+}
+
+int hifc_api_cmd_read_ack(void *hwdev, u8 dest, void *cmd, u16 size, void *ack,
+ u16 ack_size)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ struct hifc_api_cmd_chain *chain;
+
+ if (!hwdev || !cmd || (ack_size && !ack))
+ return -EINVAL;
+
+ if (!hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED) ||
+ hifc_get_mgmt_channel_status(hwdev))
+ return -EPERM;
+
+ pf_to_mgmt = ((struct hifc_hwdev *)hwdev)->pf_to_mgmt;
+ chain = pf_to_mgmt->cmd_chain[HIFC_API_CMD_POLL_READ];
+
+ if (!(((struct hifc_hwdev *)hwdev)->chip_present_flag))
+ return -EPERM;
+
+ return hifc_api_cmd_read(chain, dest, cmd, size, ack, ack_size);
+}
+
+static void __send_mgmt_ack(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ enum hifc_mod_type mod, u8 cmd, void *buf_in,
+ u16 in_size, u16 msg_id)
+{
+ u16 buf_size;
+
+ if (!in_size)
+ buf_size = BUF_OUT_DEFAULT_SIZE;
+ else
+ buf_size = in_size;
+
+ spin_lock_bh(&pf_to_mgmt->async_msg_lock);
+ /* MGMT sent sync msg, send the response */
+ send_msg_to_mgmt_async(pf_to_mgmt, mod, cmd,
+ buf_in, buf_size, HIFC_MSG_RESPONSE,
+ msg_id);
+ spin_unlock_bh(&pf_to_mgmt->async_msg_lock);
+}
+
+/**
+ * mgmt_recv_msg_handler - handler for message from mgmt cpu
+ * @pf_to_mgmt: PF to MGMT channel
+ * @recv_msg: received message details
+ **/
+static void mgmt_recv_msg_handler(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ enum hifc_mod_type mod, u8 cmd, void *buf_in,
+ u16 in_size, u16 msg_id, int need_resp)
+{
+ void *dev = pf_to_mgmt->hwdev->dev_hdl;
+ void *buf_out = pf_to_mgmt->mgmt_ack_buf;
+ enum hifc_mod_type tmp_mod = mod;
+ bool ack_first = false;
+ u16 out_size = 0;
+
+ memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
+
+ if (mod >= HIFC_MOD_HW_MAX) {
+ sdk_warn(dev, "Receive illegal message from mgmt cpu, mod = %d\n",
+ mod);
+ goto resp;
+ }
+
+ set_bit(HIFC_MGMT_MSG_CB_RUNNING,
+ &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]);
+
+ if (!pf_to_mgmt->recv_mgmt_msg_cb[mod] ||
+ !test_bit(HIFC_MGMT_MSG_CB_REG,
+ &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod])) {
+ sdk_warn(dev, "Receive mgmt callback is null, mod = %d\n",
+ mod);
+ clear_bit(HIFC_MGMT_MSG_CB_RUNNING,
+ &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]);
+ goto resp;
+ }
+
+ ack_first = hifc_mgmt_event_ack_first(mod, cmd);
+ if (ack_first && need_resp) {
+ /* send ack to mgmt first to avoid command timeout in
+ * mgmt(100ms in mgmt);
+ * mgmt to host command don't need any response data from host,
+ * just need ack from host
+ */
+ __send_mgmt_ack(pf_to_mgmt, mod, cmd, buf_out, in_size, msg_id);
+ }
+
+ pf_to_mgmt->recv_mgmt_msg_cb[tmp_mod](pf_to_mgmt->hwdev,
+ pf_to_mgmt->recv_mgmt_msg_data[tmp_mod],
+ cmd, buf_in, in_size,
+ buf_out, &out_size);
+
+ clear_bit(HIFC_MGMT_MSG_CB_RUNNING,
+ &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]);
+
+resp:
+ if (!ack_first && need_resp)
+ __send_mgmt_ack(pf_to_mgmt, mod, cmd, buf_out, out_size,
+ msg_id);
+}
+
+/**
+ * mgmt_resp_msg_handler - handler for response message from mgmt cpu
+ * @pf_to_mgmt: PF to MGMT channel
+ * @recv_msg: received message details
+ **/
+static void mgmt_resp_msg_handler(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ struct hifc_recv_msg *recv_msg)
+{
+ void *dev = pf_to_mgmt->hwdev->dev_hdl;
+
+ /* delete async msg */
+ if (recv_msg->msg_id & ASYNC_MSG_FLAG)
+ return;
+
+ spin_lock(&pf_to_mgmt->sync_event_lock);
+ if (recv_msg->msg_id == pf_to_mgmt->sync_msg_id &&
+ pf_to_mgmt->event_flag == SEND_EVENT_START) {
+ complete(&recv_msg->recv_done);
+ } else if (recv_msg->msg_id != pf_to_mgmt->sync_msg_id) {
+ sdk_err(dev, "Send msg id(0x%x) recv msg id(0x%x) dismatch, event state=%d\n",
+ pf_to_mgmt->sync_msg_id, recv_msg->msg_id,
+ pf_to_mgmt->event_flag);
+ } else {
+ sdk_err(dev, "Wait timeout, send msg id(0x%x) recv msg id(0x%x), event state=%d!\n",
+ pf_to_mgmt->sync_msg_id, recv_msg->msg_id,
+ pf_to_mgmt->event_flag);
+ }
+ spin_unlock(&pf_to_mgmt->sync_event_lock);
+}
+
+static void recv_mgmt_msg_work_handler(struct work_struct *work)
+{
+ struct hifc_mgmt_msg_handle_work *mgmt_work =
+ container_of(work, struct hifc_mgmt_msg_handle_work, work);
+
+ mgmt_recv_msg_handler(mgmt_work->pf_to_mgmt, mgmt_work->mod,
+ mgmt_work->cmd, mgmt_work->msg,
+ mgmt_work->msg_len, mgmt_work->msg_id,
+ !mgmt_work->async_mgmt_to_pf);
+
+ kfree(mgmt_work->msg);
+ kfree(mgmt_work);
+}
+
+static bool check_mgmt_seq_id_and_seg_len(struct hifc_recv_msg *recv_msg,
+ u8 seq_id, u8 seg_len)
+{
+ if (seq_id > MGMT_MSG_MAX_SEQ_ID || seg_len > SEGMENT_LEN)
+ return false;
+
+ if (seq_id == 0) {
+ recv_msg->seq_id = seq_id;
+ } else {
+ if (seq_id != recv_msg->seq_id + 1)
+ return false;
+ recv_msg->seq_id = seq_id;
+ }
+
+ return true;
+}
+
+/**
+ * recv_mgmt_msg_handler - handler a message from mgmt cpu
+ * @pf_to_mgmt: PF to MGMT channel
+ * @header: the header of the message
+ * @recv_msg: received message details
+ **/
+static void recv_mgmt_msg_handler(struct hifc_msg_pf_to_mgmt *pf_to_mgmt,
+ u8 *header, struct hifc_recv_msg *recv_msg)
+{
+ struct hifc_mgmt_msg_handle_work *mgmt_work;
+ u64 mbox_header = *((u64 *)header);
+ void *msg_body = header + sizeof(mbox_header);
+ u8 seq_id, seq_len;
+ u32 offset;
+ u64 dir;
+
+ /* Don't need to get anything from hw when cmd is async */
+ dir = HIFC_MSG_HEADER_GET(mbox_header, DIRECTION);
+ if (dir == HIFC_MSG_RESPONSE &&
+ HIFC_MSG_HEADER_GET(mbox_header, MSG_ID) & ASYNC_MSG_FLAG)
+ return;
+
+ seq_len = HIFC_MSG_HEADER_GET(mbox_header, SEG_LEN);
+ seq_id = HIFC_MSG_HEADER_GET(mbox_header, SEQID);
+
+ if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len)) {
+ sdk_err(pf_to_mgmt->hwdev->dev_hdl,
+ "Mgmt msg sequence id and segment length check fail, front seq_id: 0x%x, current seq_id: 0x%x, seg len: 0x%x\n",
+ recv_msg->seq_id, seq_id, seq_len);
+ /* set seq_id to invalid seq_id */
+ recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
+ return;
+ }
+
+ offset = seq_id * SEGMENT_LEN;
+ memcpy((u8 *)recv_msg->msg + offset, msg_body, seq_len);
+
+ if (!HIFC_MSG_HEADER_GET(mbox_header, LAST))
+ return;
+
+ recv_msg->cmd = HIFC_MSG_HEADER_GET(mbox_header, CMD);
+ recv_msg->mod = HIFC_MSG_HEADER_GET(mbox_header, MODULE);
+ recv_msg->async_mgmt_to_pf = HIFC_MSG_HEADER_GET(mbox_header,
+ ASYNC_MGMT_TO_PF);
+ recv_msg->msg_len = HIFC_MSG_HEADER_GET(mbox_header, MSG_LEN);
+ recv_msg->msg_id = HIFC_MSG_HEADER_GET(mbox_header, MSG_ID);
+ recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
+
+ if (HIFC_MSG_HEADER_GET(mbox_header, DIRECTION) ==
+ HIFC_MSG_RESPONSE) {
+ mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
+ return;
+ }
+
+ mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
+ if (!mgmt_work) {
+ sdk_err(pf_to_mgmt->hwdev->dev_hdl,
+ "Allocate mgmt work memory failed\n");
+ return;
+ }
+
+ if (recv_msg->msg_len) {
+ mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
+ if (!mgmt_work->msg) {
+ sdk_err(pf_to_mgmt->hwdev->dev_hdl, "Allocate mgmt msg memory failed\n");
+ kfree(mgmt_work);
+ return;
+ }
+ }
+
+ mgmt_work->pf_to_mgmt = pf_to_mgmt;
+ mgmt_work->msg_len = recv_msg->msg_len;
+ memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
+ mgmt_work->msg_id = recv_msg->msg_id;
+ mgmt_work->mod = recv_msg->mod;
+ mgmt_work->cmd = recv_msg->cmd;
+ mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
+
+ INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
+ queue_work(pf_to_mgmt->workq, &mgmt_work->work);
+}
+
+/**
+ * hifc_mgmt_msg_aeqe_handler - handler for a mgmt message event
+ * @hwdev: the pointer to hw device
+ * @header: the header of the message
+ * @size: unused
+ **/
+void hifc_mgmt_msg_aeqe_handler(void *hwdev, u8 *header, u8 size)
+{
+ struct hifc_hwdev *dev = (struct hifc_hwdev *)hwdev;
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ struct hifc_recv_msg *recv_msg;
+ bool is_send_dir = false;
+
+ pf_to_mgmt = dev->pf_to_mgmt;
+
+ is_send_dir = (HIFC_MSG_HEADER_GET(*(u64 *)header, DIRECTION) ==
+ HIFC_MSG_DIRECT_SEND) ? true : false;
+
+ recv_msg = is_send_dir ? &pf_to_mgmt->recv_msg_from_mgmt :
+ &pf_to_mgmt->recv_resp_msg_from_mgmt;
+
+ recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
+}
+
+/**
+ * alloc_recv_msg - allocate received message memory
+ * @recv_msg: pointer that will hold the allocated data
+ * Return: 0 - success, negative - failure
+ **/
+static int alloc_recv_msg(struct hifc_recv_msg *recv_msg)
+{
+ recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
+
+ recv_msg->msg = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
+ if (!recv_msg->msg)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * free_recv_msg - free received message memory
+ * @recv_msg: pointer that holds the allocated data
+ **/
+static void free_recv_msg(struct hifc_recv_msg *recv_msg)
+{
+ kfree(recv_msg->msg);
+}
+
+/**
+ * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
+ * @pf_to_mgmt: PF to MGMT channel
+ * Return: 0 - success, negative - failure
+ **/
+static int alloc_msg_buf(struct hifc_msg_pf_to_mgmt *pf_to_mgmt)
+{
+ int err;
+ void *dev = pf_to_mgmt->hwdev->dev_hdl;
+
+ err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+ if (err) {
+ sdk_err(dev, "Failed to allocate recv msg\n");
+ return err;
+ }
+
+ err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
+ if (err) {
+ sdk_err(dev, "Failed to allocate resp recv msg\n");
+ goto alloc_msg_for_resp_err;
+ }
+
+ pf_to_mgmt->async_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
+ if (!pf_to_mgmt->async_msg_buf) {
+ err = -ENOMEM;
+ goto async_msg_buf_err;
+ }
+
+ pf_to_mgmt->sync_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
+ if (!pf_to_mgmt->sync_msg_buf) {
+ err = -ENOMEM;
+ goto sync_msg_buf_err;
+ }
+
+ pf_to_mgmt->mgmt_ack_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
+ if (!pf_to_mgmt->mgmt_ack_buf) {
+ err = -ENOMEM;
+ goto ack_msg_buf_err;
+ }
+
+ return 0;
+
+ack_msg_buf_err:
+ kfree(pf_to_mgmt->sync_msg_buf);
+
+sync_msg_buf_err:
+ kfree(pf_to_mgmt->async_msg_buf);
+
+async_msg_buf_err:
+ free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
+
+alloc_msg_for_resp_err:
+ free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+ return err;
+}
+
+/**
+ * free_msg_buf - free all the message buffers of PF to MGMT channel
+ * @pf_to_mgmt: PF to MGMT channel
+ **/
+static void free_msg_buf(struct hifc_msg_pf_to_mgmt *pf_to_mgmt)
+{
+ kfree(pf_to_mgmt->mgmt_ack_buf);
+ kfree(pf_to_mgmt->sync_msg_buf);
+ kfree(pf_to_mgmt->async_msg_buf);
+
+ free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
+ free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+}
+
+/**
+ * hifc_pf_to_mgmt_init - initialize PF to MGMT channel
+ * @hwdev: the pointer to hw device
+ * Return: 0 - success, negative - failure
+ **/
+int hifc_pf_to_mgmt_init(struct hifc_hwdev *hwdev)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ void *dev = hwdev->dev_hdl;
+ int err;
+
+ pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL);
+ if (!pf_to_mgmt)
+ return -ENOMEM;
+
+ hwdev->pf_to_mgmt = pf_to_mgmt;
+ pf_to_mgmt->hwdev = hwdev;
+ spin_lock_init(&pf_to_mgmt->async_msg_lock);
+ spin_lock_init(&pf_to_mgmt->sync_event_lock);
+ sema_init(&pf_to_mgmt->sync_msg_lock, 1);
+ pf_to_mgmt->workq = create_singlethread_workqueue(HIFC_MGMT_WQ_NAME);
+ if (!pf_to_mgmt->workq) {
+ sdk_err(dev, "Failed to initialize MGMT workqueue\n");
+ err = -ENOMEM;
+ goto create_mgmt_workq_err;
+ }
+
+ err = alloc_msg_buf(pf_to_mgmt);
+ if (err) {
+ sdk_err(dev, "Failed to allocate msg buffers\n");
+ goto alloc_msg_buf_err;
+ }
+
+ err = hifc_api_cmd_init(hwdev, pf_to_mgmt->cmd_chain);
+ if (err) {
+ sdk_err(dev, "Failed to init the api cmd chains\n");
+ goto api_cmd_init_err;
+ }
+
+ return 0;
+
+api_cmd_init_err:
+ free_msg_buf(pf_to_mgmt);
+
+alloc_msg_buf_err:
+ destroy_workqueue(pf_to_mgmt->workq);
+
+create_mgmt_workq_err:
+ kfree(pf_to_mgmt);
+
+ return err;
+}
+
+/**
+ * hifc_pf_to_mgmt_free - free PF to MGMT channel
+ * @hwdev: the pointer to hw device
+ **/
+void hifc_pf_to_mgmt_free(struct hifc_hwdev *hwdev)
+{
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
+
+ /* destroy workqueue before free related pf_to_mgmt resources in case of
+ * illegal resource access
+ */
+ destroy_workqueue(pf_to_mgmt->workq);
+ hifc_api_cmd_free(pf_to_mgmt->cmd_chain);
+ free_msg_buf(pf_to_mgmt);
+ kfree(pf_to_mgmt);
+}
+
+void hifc_flush_mgmt_workq(void *hwdev)
+{
+ struct hifc_hwdev *dev = (struct hifc_hwdev *)hwdev;
+
+ flush_workqueue(dev->aeqs->workq);
+
+ if (hifc_func_type(dev) != TYPE_VF &&
+ hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_MGMT_INITED))
+ flush_workqueue(dev->pf_to_mgmt->workq);
+}
+
+int hifc_clp_pf_to_mgmt_init(struct hifc_hwdev *hwdev)
+{
+ struct hifc_clp_pf_to_mgmt *clp_pf_to_mgmt;
+
+ clp_pf_to_mgmt = kzalloc(sizeof(*clp_pf_to_mgmt), GFP_KERNEL);
+ if (!clp_pf_to_mgmt)
+ return -ENOMEM;
+
+ clp_pf_to_mgmt->clp_msg_buf = kzalloc(HIFC_CLP_INPUT_BUFFER_LEN_HOST,
+ GFP_KERNEL);
+ if (!clp_pf_to_mgmt->clp_msg_buf) {
+ kfree(clp_pf_to_mgmt);
+ return -ENOMEM;
+ }
+ sema_init(&clp_pf_to_mgmt->clp_msg_lock, 1);
+
+ hwdev->clp_pf_to_mgmt = clp_pf_to_mgmt;
+
+ return 0;
+}
+
+void hifc_clp_pf_to_mgmt_free(struct hifc_hwdev *hwdev)
+{
+ struct hifc_clp_pf_to_mgmt *clp_pf_to_mgmt = hwdev->clp_pf_to_mgmt;
+
+ kfree(clp_pf_to_mgmt->clp_msg_buf);
+ kfree(clp_pf_to_mgmt);
+}
+
diff --git a/drivers/scsi/huawei/hifc/hifc_mgmt.h b/drivers/scsi/huawei/hifc/hifc_mgmt.h
new file mode 100644
index 000000000000..2adcfe2968c1
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_mgmt.h
@@ -0,0 +1,407 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_MGMT_H_
+#define HIFC_MGMT_H_
+
+#define HIFC_MSG_HEADER_MSG_LEN_SHIFT 0
+#define HIFC_MSG_HEADER_MODULE_SHIFT 11
+#define HIFC_MSG_HEADER_SEG_LEN_SHIFT 16
+#define HIFC_MSG_HEADER_NO_ACK_SHIFT 22
+#define HIFC_MSG_HEADER_ASYNC_MGMT_TO_PF_SHIFT 23
+#define HIFC_MSG_HEADER_SEQID_SHIFT 24
+#define HIFC_MSG_HEADER_LAST_SHIFT 30
+#define HIFC_MSG_HEADER_DIRECTION_SHIFT 31
+#define HIFC_MSG_HEADER_CMD_SHIFT 32
+#define HIFC_MSG_HEADER_PCI_INTF_IDX_SHIFT 48
+#define HIFC_MSG_HEADER_P2P_IDX_SHIFT 50
+#define HIFC_MSG_HEADER_MSG_ID_SHIFT 54
+
+#define HIFC_MSG_HEADER_MSG_LEN_MASK 0x7FF
+#define HIFC_MSG_HEADER_MODULE_MASK 0x1F
+#define HIFC_MSG_HEADER_SEG_LEN_MASK 0x3F
+#define HIFC_MSG_HEADER_NO_ACK_MASK 0x1
+#define HIFC_MSG_HEADER_ASYNC_MGMT_TO_PF_MASK 0x1
+#define HIFC_MSG_HEADER_SEQID_MASK 0x3F
+#define HIFC_MSG_HEADER_LAST_MASK 0x1
+#define HIFC_MSG_HEADER_DIRECTION_MASK 0x1
+#define HIFC_MSG_HEADER_CMD_MASK 0xFF
+#define HIFC_MSG_HEADER_PCI_INTF_IDX_MASK 0x3
+#define HIFC_MSG_HEADER_P2P_IDX_MASK 0xF
+#define HIFC_MSG_HEADER_MSG_ID_MASK 0x3FF
+
+#define HIFC_MSG_HEADER_GET(val, member) \
+ (((val) >> HIFC_MSG_HEADER_##member##_SHIFT) & \
+ HIFC_MSG_HEADER_##member##_MASK)
+
+#define HIFC_MSG_HEADER_SET(val, member) \
+ ((u64)((val) & HIFC_MSG_HEADER_##member##_MASK) << \
+ HIFC_MSG_HEADER_##member##_SHIFT)
+
+#define HIFC_MGMT_WQ_NAME "hifc_mgmt"
+
+/*CLP*/
+enum clp_data_type {
+ HIFC_CLP_REQ_HOST = 0,
+ HIFC_CLP_RSP_HOST = 1
+};
+
+enum clp_reg_type {
+ HIFC_CLP_BA_HOST = 0,
+ HIFC_CLP_SIZE_HOST = 1,
+ HIFC_CLP_LEN_HOST = 2,
+ HIFC_CLP_START_REQ_HOST = 3,
+ HIFC_CLP_READY_RSP_HOST = 4
+};
+
+/* cmd of mgmt CPU message for HW module */
+enum hifc_mgmt_cmd {
+ HIFC_MGMT_CMD_RESET_MGMT = 0x0,
+ HIFC_MGMT_CMD_START_FLR = 0x1,
+ HIFC_MGMT_CMD_FLUSH_DOORBELL = 0x2,
+ HIFC_MGMT_CMD_CMDQ_CTXT_SET = 0x10,
+ HIFC_MGMT_CMD_VAT_SET = 0x12,
+ HIFC_MGMT_CMD_L2NIC_SQ_CI_ATTR_SET = 0x14,
+ HIFC_MGMT_CMD_PPF_TMR_SET = 0x22,
+ HIFC_MGMT_CMD_PPF_HT_GPA_SET = 0x23,
+ HIFC_MGMT_CMD_RES_STATE_SET = 0x24,
+ HIFC_MGMT_CMD_FUNC_TMR_BITMAT_SET = 0x32,
+ HIFC_MGMT_CMD_CEQ_CTRL_REG_WR_BY_UP = 0x33,
+ HIFC_MGMT_CMD_MSI_CTRL_REG_WR_BY_UP,
+ HIFC_MGMT_CMD_MSI_CTRL_REG_RD_BY_UP,
+ HIFC_MGMT_CMD_FAULT_REPORT = 0x37,
+ HIFC_MGMT_CMD_HEART_LOST_REPORT = 0x38,
+ HIFC_MGMT_CMD_SYNC_TIME = 0x46,
+ HIFC_MGMT_CMD_REG_READ = 0x48,
+ HIFC_MGMT_CMD_L2NIC_RESET = 0x4b,
+ HIFC_MGMT_CMD_ACTIVATE_FW = 0x4F,
+ HIFC_MGMT_CMD_PAGESIZE_SET = 0x50,
+ HIFC_MGMT_CMD_GET_BOARD_INFO = 0x52,
+ HIFC_MGMT_CMD_WATCHDOG_INFO = 0x56,
+ HIFC_MGMT_CMD_FMW_ACT_NTC = 0x57,
+ HIFC_MGMT_CMD_PCIE_DFX_NTC = 0x65,
+ HIFC_MGMT_CMD_PCIE_DFX_GET = 0x66,
+ HIFC_MGMT_CMD_GET_HOST_INFO = 0x67,
+ HIFC_MGMT_CMD_GET_PHY_INIT_STATUS = 0x6A,
+ HIFC_MGMT_CMD_HEARTBEAT_EVENT = 0x6C,
+};
+
+#define HIFC_CLP_REG_GAP 0x20
+#define HIFC_CLP_INPUT_BUFFER_LEN_HOST 2048UL
+#define HIFC_CLP_OUTPUT_BUFFER_LEN_HOST 2048UL
+#define HIFC_CLP_DATA_UNIT_HOST 4UL
+#define HIFC_BAR01_GLOABAL_CTL_OFFSET 0x4000
+#define HIFC_BAR01_CLP_OFFSET 0x5000
+
+#define HIFC_CLP_SRAM_SIZE_REG (HIFC_BAR01_GLOABAL_CTL_OFFSET + 0x220)
+#define HIFC_CLP_REQ_SRAM_BA_REG (HIFC_BAR01_GLOABAL_CTL_OFFSET + 0x224)
+#define HIFC_CLP_RSP_SRAM_BA_REG (HIFC_BAR01_GLOABAL_CTL_OFFSET + 0x228)
+#define HIFC_CLP_REQ_REG (HIFC_BAR01_GLOABAL_CTL_OFFSET + 0x22c)
+#define HIFC_CLP_RSP_REG (HIFC_BAR01_GLOABAL_CTL_OFFSET + 0x230)
+#define HIFC_CLP_REG(member) (HIFC_CLP_##member##_REG)
+
+#define HIFC_CLP_REQ_DATA (HIFC_BAR01_CLP_OFFSET)
+#define HIFC_CLP_RSP_DATA (HIFC_BAR01_CLP_OFFSET + 0x1000)
+#define HIFC_CLP_DATA(member) (HIFC_CLP_##member##_DATA)
+
+#define HIFC_CLP_SRAM_SIZE_OFFSET 16
+#define HIFC_CLP_SRAM_BASE_OFFSET 0
+#define HIFC_CLP_LEN_OFFSET 0
+#define HIFC_CLP_START_OFFSET 31
+#define HIFC_CLP_READY_OFFSET 31
+#define HIFC_CLP_OFFSET(member) (HIFC_CLP_##member##_OFFSET)
+
+#define HIFC_CLP_SRAM_SIZE_BIT_LEN 0x7ffUL
+#define HIFC_CLP_SRAM_BASE_BIT_LEN 0x7ffffffUL
+#define HIFC_CLP_LEN_BIT_LEN 0x7ffUL
+#define HIFC_CLP_START_BIT_LEN 0x1UL
+#define HIFC_CLP_READY_BIT_LEN 0x1UL
+#define HIFC_CLP_MASK(member) (HIFC_CLP_##member##_BIT_LEN)
+
+#define HIFC_CLP_DELAY_CNT_MAX 200UL
+#define HIFC_CLP_SRAM_SIZE_REG_MAX 0x3ff
+#define HIFC_CLP_SRAM_BASE_REG_MAX 0x7ffffff
+#define HIFC_CLP_LEN_REG_MAX 0x3ff
+#define HIFC_CLP_START_OR_READY_REG_MAX 0x1
+#define HIFC_MGMT_CMD_UNSUPPORTED 0xFF
+
+enum hifc_msg_direction_type {
+ HIFC_MSG_DIRECT_SEND = 0,
+ HIFC_MSG_RESPONSE = 1
+};
+
+enum hifc_msg_segment_type {
+ NOT_LAST_SEGMENT = 0,
+ LAST_SEGMENT = 1,
+};
+
+enum hifc_mgmt_msg_type {
+ ASYNC_MGMT_MSG = 0,
+ SYNC_MGMT_MSG = 1,
+};
+
+enum hifc_msg_ack_type {
+ HIFC_MSG_ACK = 0,
+ HIFC_MSG_NO_ACK = 1,
+};
+
+struct hifc_recv_msg {
+ void *msg;
+
+ struct completion recv_done;
+
+ u16 msg_len;
+ enum hifc_mod_type mod;
+ u8 cmd;
+ u8 seq_id;
+ u16 msg_id;
+ int async_mgmt_to_pf;
+};
+
+struct hifc_msg_head {
+ u8 status;
+ u8 version;
+ u8 resp_aeq_num;
+ u8 rsvd0[5];
+};
+
+#define HIFC_COMM_SELF_CMD_MAX 8
+
+struct comm_up_self_msg_sub_info {
+ u8 cmd;
+ comm_up_self_msg_proc proc;
+};
+
+struct comm_up_self_msg_info {
+ u8 cmd_num;
+ struct comm_up_self_msg_sub_info info[HIFC_COMM_SELF_CMD_MAX];
+};
+
+enum comm_pf_to_mgmt_event_state {
+ SEND_EVENT_UNINIT = 0,
+ SEND_EVENT_START,
+ SEND_EVENT_FAIL,
+ SEND_EVENT_TIMEOUT,
+ SEND_EVENT_END,
+};
+
+enum hifc_mgmt_msg_cb_state {
+ HIFC_MGMT_MSG_CB_REG = 0,
+ HIFC_MGMT_MSG_CB_RUNNING,
+};
+
+struct hifc_clp_pf_to_mgmt {
+ struct semaphore clp_msg_lock;
+ void *clp_msg_buf;
+};
+
+struct hifc_msg_pf_to_mgmt {
+ struct hifc_hwdev *hwdev;
+
+ /* Async cmd can not be scheduling */
+ spinlock_t async_msg_lock;
+ struct semaphore sync_msg_lock;
+
+ struct workqueue_struct *workq;
+
+ void *async_msg_buf;
+ void *sync_msg_buf;
+ void *mgmt_ack_buf;
+
+ struct hifc_recv_msg recv_msg_from_mgmt;
+ struct hifc_recv_msg recv_resp_msg_from_mgmt;
+
+ u16 async_msg_id;
+ u16 sync_msg_id;
+
+ struct hifc_api_cmd_chain *cmd_chain[HIFC_API_CMD_MAX];
+
+ hifc_mgmt_msg_cb recv_mgmt_msg_cb[HIFC_MOD_HW_MAX];
+ void *recv_mgmt_msg_data[HIFC_MOD_HW_MAX];
+ unsigned long mgmt_msg_cb_state[HIFC_MOD_HW_MAX];
+
+ struct comm_up_self_msg_info proc;
+
+ /* lock when sending msg */
+ spinlock_t sync_event_lock;
+ enum comm_pf_to_mgmt_event_state event_flag;
+};
+
+struct hifc_mgmt_msg_handle_work {
+ struct work_struct work;
+ struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
+ void *msg;
+ u16 msg_len;
+ enum hifc_mod_type mod;
+ u8 cmd;
+ u16 msg_id;
+ int async_mgmt_to_pf;
+};
+
+/* show each drivers only such as nic_service_cap,
+ * toe_service_cap structure, but not show service_cap
+ */
+enum hifc_service_type {
+ SERVICE_T_NIC = 0,
+
+ SERVICE_T_FC = 5,
+
+ SERVICE_T_MAX,
+
+ /* Only used for interruption resource management,
+ * mark the request module
+ */
+ SERVICE_T_INTF = (1 << 15),
+ SERVICE_T_CQM = (1 << 16),
+};
+
+/* NIC service capability
+ * 1, The chip supports NIC RQ is 1K
+ * 2, PF/VF RQ specifications:
+ * disable RSS:
+ * disable VMDq: Each PF/VF at most 8 RQ
+ * enable the VMDq: Each PF/VF at most 1K RQ
+ * enable the RSS:
+ * disable VMDq: each PF at most 64 RQ, VF at most 32 RQ
+ * enable the VMDq: Each PF/VF at most 1K RQ
+ *
+ * 3, The chip supports NIC SQ is 1K
+ * 4, PF/VF SQ specifications:
+ * disable RSS:
+ * disable VMDq: Each PF/VF at most 8 SQ
+ * enable the VMDq: Each PF/VF at most 1K SQ
+ * enable the RSS:
+ * disable VMDq: each PF at most 64 SQ, VF at most 32 SQ
+ * enable the VMDq: Each PF/VF at most 1K SQ
+ */
+struct nic_service_cap {
+ /* PF resources*/
+ u16 max_sqs;
+ u16 max_rqs;
+
+ /* VF resources, vf obtain through the MailBox mechanism from
+ * according PF
+ */
+ u16 vf_max_sqs;
+ u16 vf_max_rqs;
+ bool lro_en; /* LRO feature enable bit*/
+ u8 lro_sz; /* LRO context space: n*16B */
+ u8 tso_sz; /* TSO context space: n*16B */
+
+ u16 max_queue_allowed;
+};
+
+/* PF FC service resource structure defined*/
+struct dev_fc_svc_cap {
+ /* PF Parent QPC */
+ u32 max_parent_qpc_num; /* max number is 2048*/
+
+ /* PF Child QPC */
+ u32 max_child_qpc_num; /* max number is 2048*/
+
+ /* PF SCQ */
+ u32 scq_num; /* 16 */
+
+ /* PF supports SRQ*/
+ u32 srq_num; /* Number of SRQ is 2*/
+
+ u8 vp_id_start;
+ u8 vp_id_end;
+};
+
+/* FC services*/
+struct fc_service_cap {
+ struct dev_fc_svc_cap dev_fc_cap;
+
+ /* Parent QPC */
+ u32 parent_qpc_size; /* 256B */
+
+ /* Child QPC */
+ u32 child_qpc_size; /* 256B */
+
+ /* SQ */
+ u32 sqe_size; /* 128B(in linked list mode)*/
+
+ /* SCQ */
+ u32 scqc_size; /* Size of the Context 32B*/
+ u32 scqe_size; /* 64B */
+
+ /* SRQ */
+ u32 srqc_size; /* Size of SRQ Context (64B)*/
+ u32 srqe_size; /* 32B */
+};
+
+bool hifc_support_fc(void *hwdev, struct fc_service_cap *cap);
+
+/* Service interface for obtaining service_cap public fields*/
+/* Obtain service_cap.host_oq_id_mask_val*/
+u8 hifc_host_oq_id_mask(void *hwdev);
+
+/* Obtain service_cap.dev_cap.max_sqs*/
+u16 hifc_func_max_qnum(void *hwdev);
+
+/* The following information is obtained from the bar space
+ * which is recorded by SDK layer.
+ * Here provide parameter query interface for service
+ */
+/* func_attr.glb_func_idx, global function index */
+u16 hifc_global_func_id(void *hwdev);
+/* func_attr.intr_num, MSI-X table entry in function*/
+enum intr_type {
+ INTR_TYPE_MSIX,
+ INTR_TYPE_MSI,
+ INTR_TYPE_INT,
+ INTR_TYPE_NONE,
+};
+
+u8 hifc_pcie_itf_id(void *hwdev); /* func_attr.itf_idx, pcie interface index */
+
+/* func_attr.func_type, 0-PF 1-VF 2-PPF */
+enum func_type hifc_func_type(void *hwdev);
+
+u8 hifc_ppf_idx(void *hwdev);
+
+enum hifc_msix_state {
+ HIFC_MSIX_ENABLE,
+ HIFC_MSIX_DISABLE,
+};
+
+void hifc_set_msix_state(void *hwdev, u16 msix_idx,
+ enum hifc_msix_state flag);
+
+/* Defines the IRQ information structure*/
+struct irq_info {
+ u16 msix_entry_idx; /* IRQ corresponding index number */
+ u32 irq_id; /* the IRQ number from OS */
+};
+
+int hifc_alloc_irqs(void *hwdev, enum hifc_service_type type, u16 req_num,
+ struct irq_info *irq_info_array, u16 *resp_num);
+void hifc_free_irq(void *hwdev, enum hifc_service_type type, u32 irq_id);
+
+int hifc_sync_time(void *hwdev, u64 time);
+void hifc_disable_mgmt_msg_report(void *hwdev);
+void hifc_set_func_deinit_flag(void *hwdev);
+void hifc_flush_mgmt_workq(void *hwdev);
+int hifc_global_func_id_get(void *hwdev, u16 *func_id);
+u16 hifc_global_func_id_hw(void *hwdev);
+int hifc_pf_to_mgmt_no_ack(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size);
+void hifc_mgmt_msg_aeqe_handler(void *handle, u8 *header, u8 size);
+int hifc_pf_to_mgmt_init(struct hifc_hwdev *hwdev);
+void hifc_pf_to_mgmt_free(struct hifc_hwdev *hwdev);
+int hifc_pf_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size, void *buf_out,
+ u16 *out_size, u32 timeout);
+int hifc_pf_to_mgmt_async(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ void *buf_in, u16 in_size);
+int hifc_pf_clp_to_mgmt(void *hwdev, enum hifc_mod_type mod, u8 cmd,
+ const void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
+int hifc_clp_pf_to_mgmt_init(struct hifc_hwdev *hwdev);
+void hifc_clp_pf_to_mgmt_free(struct hifc_hwdev *hwdev);
+
+#endif
diff --git a/drivers/scsi/huawei/hifc/hifc_sml.c b/drivers/scsi/huawei/hifc/hifc_sml.c
new file mode 100644
index 000000000000..2d04ff6ed5ff
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_sml.c
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/types.h>
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwdev.h"
+#include "hifc_sml.h"
+
+#ifndef HTONL
+#define HTONL(x) \
+ ((((x) & 0x000000ff) << 24) \
+ | (((x) & 0x0000ff00) << 8) \
+ | (((x) & 0x00ff0000) >> 8) \
+ | (((x) & 0xff000000) >> 24))
+#endif
+
+static void sml_ctr_htonl_n(u32 *node, u32 len)
+{
+ u32 i;
+
+ for (i = 0; i < len; i++) {
+ *node = HTONL(*node);
+ node++;
+ }
+}
+
+static void hifc_sml_ctr_read_build_req(struct chipif_sml_ctr_rd_req_s *msg,
+ u8 instance_id, u8 op_id,
+ u8 ack, u32 ctr_id, u32 init_val)
+{
+ msg->head.value = 0;
+ msg->head.bs.instance = instance_id;
+ msg->head.bs.op_id = op_id;
+ msg->head.bs.ack = ack;
+ msg->head.value = HTONL(msg->head.value);
+
+ msg->ctr_id = ctr_id;
+ msg->ctr_id = HTONL(msg->ctr_id);
+
+ msg->initial = init_val;
+}
+
+static void hifc_sml_ctr_write_build_req(struct chipif_sml_ctr_wr_req_s *msg,
+ u8 instance_id, u8 op_id,
+ u8 ack, u32 ctr_id,
+ u64 val1, u64 val2)
+{
+ msg->head.value = 0;
+ msg->head.bs.instance = instance_id;
+ msg->head.bs.op_id = op_id;
+ msg->head.bs.ack = ack;
+ msg->head.value = HTONL(msg->head.value);
+
+ msg->ctr_id = ctr_id;
+ msg->ctr_id = HTONL(msg->ctr_id);
+
+ msg->value1_h = val1 >> 32;
+ msg->value1_l = val1 & 0xFFFFFFFF;
+
+ msg->value2_h = val2 >> 32;
+ msg->value2_l = val2 & 0xFFFFFFFF;
+}
+
+/**
+ * hifc_sm_ctr_rd32 - small single 32 counter read
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @instance: instance value
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ */
+int hifc_sm_ctr_rd32(void *hwdev, u8 node, u8 instance, u32 ctr_id, u32 *value)
+{
+ struct chipif_sml_ctr_rd_req_s req;
+ union ctr_rd_rsp_u rsp;
+ int ret;
+
+ if (!hwdev || !value)
+ return -EFAULT;
+
+ hifc_sml_ctr_read_build_req(&req, instance, CHIPIF_SM_CTR_OP_READ,
+ CHIPIF_ACK, ctr_id, 0);
+
+ ret = hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req),
+ (void *)&rsp, (unsigned short)sizeof(rsp));
+ if (ret) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Sm 32bit counter read fail, err(%d)\n", ret);
+ return ret;
+ }
+ sml_ctr_htonl_n((u32 *)&rsp, 4);
+ *value = rsp.bs_ss32_rsp.value1;
+
+ return 0;
+}
+
+/**
+ * hifc_sm_ctr_rd32_clear - small single 32 counter read and clear to zero
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @instance: instance value
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ * according to ACN error code (ERR_OK, ERR_PARAM, ERR_FAILED...etc)
+ */
+int hifc_sm_ctr_rd32_clear(void *hwdev, u8 node, u8 instance,
+ u32 ctr_id, u32 *value)
+{
+ struct chipif_sml_ctr_rd_req_s req;
+ union ctr_rd_rsp_u rsp;
+ int ret;
+
+ if (!hwdev || !value)
+ return -EFAULT;
+
+ hifc_sml_ctr_read_build_req(&req, instance,
+ CHIPIF_SM_CTR_OP_READ_CLEAR,
+ CHIPIF_ACK, ctr_id, 0);
+
+ ret = hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req),
+ (void *)&rsp, (unsigned short)sizeof(rsp));
+
+ if (ret) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Sm 32bit counter clear fail, err(%d)\n", ret);
+ return ret;
+ }
+ sml_ctr_htonl_n((u32 *)&rsp, 4);
+ *value = rsp.bs_ss32_rsp.value1;
+
+ return 0;
+}
+
+/**
+ * hifc_sm_ctr_wr32 - small single 32 counter write
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @instance: instance value
+ * @ctr_id: counter id
+ * @value: write counter value
+ * Return: 0 - success, negative - failure
+ */
+int hifc_sm_ctr_wr32(void *hwdev, u8 node, u8 instance, u32 ctr_id, u32 value)
+{
+ struct chipif_sml_ctr_wr_req_s req;
+ struct chipif_sml_ctr_wr_rsp_s rsp;
+
+ if (!hwdev)
+ return -EFAULT;
+
+ hifc_sml_ctr_write_build_req(&req, instance, CHIPIF_SM_CTR_OP_WRITE,
+ CHIPIF_NOACK, ctr_id, (u64)value, 0ULL);
+
+ return hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req), (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+}
+
+/**
+ * hifc_sm_ctr_rd64 - big counter 64 read
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @instance: instance value
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ */
+int hifc_sm_ctr_rd64(void *hwdev, u8 node, u8 instance, u32 ctr_id, u64 *value)
+{
+ struct chipif_sml_ctr_rd_req_s req;
+ union ctr_rd_rsp_u rsp;
+ int ret;
+
+ if (!hwdev || !value)
+ return -EFAULT;
+
+ hifc_sml_ctr_read_build_req(&req, instance, CHIPIF_SM_CTR_OP_READ,
+ CHIPIF_ACK, ctr_id, 0);
+
+ ret = hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req), (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+ if (ret) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Sm 64bit counter read fail err(%d)\n", ret);
+ return ret;
+ }
+ sml_ctr_htonl_n((u32 *)&rsp, 4);
+ *value = ((u64)rsp.bs_bs64_rsp.value1 << 32) | rsp.bs_bs64_rsp.value2;
+
+ return 0;
+}
+
+/**
+ * hifc_sm_ctr_wr64 - big single 64 counter write
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @instance: instance value
+ * @ctr_id: counter id
+ * @value: write counter value
+ * Return: 0 - success, negative - failure
+ */
+int hifc_sm_ctr_wr64(void *hwdev, u8 node, u8 instance, u32 ctr_id, u64 value)
+{
+ struct chipif_sml_ctr_wr_req_s req;
+ struct chipif_sml_ctr_wr_rsp_s rsp;
+
+ if (!hwdev)
+ return -EFAULT;
+
+ hifc_sml_ctr_write_build_req(&req, instance, CHIPIF_SM_CTR_OP_WRITE,
+ CHIPIF_NOACK, ctr_id, value, 0ULL);
+
+ return hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req), (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+}
+
+/**
+ * hifc_sm_ctr_rd64_pair - big pair 128 counter read
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @instance: instance value
+ * @ctr_id: counter id
+ * @value1: read counter value ptr
+ * @value2: read counter value ptr
+ * Return: 0 - success, negative - failure
+ */
+int hifc_sm_ctr_rd64_pair(void *hwdev, u8 node, u8 instance,
+ u32 ctr_id, u64 *value1, u64 *value2)
+{
+ struct chipif_sml_ctr_rd_req_s req;
+ union ctr_rd_rsp_u rsp;
+ int ret;
+
+ if (!hwdev || (0 != (ctr_id & 0x1)) || !value1 || !value2) {
+ pr_err("Hwdev(0x%p) or value1(0x%p) or value2(0x%p) is NULL or ctr_id(%d) is odd number\n",
+ hwdev, value1, value2, ctr_id);
+ return -EFAULT;
+ }
+
+ hifc_sml_ctr_read_build_req(&req, instance, CHIPIF_SM_CTR_OP_READ,
+ CHIPIF_ACK, ctr_id, 0);
+
+ ret = hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req), (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+ if (ret) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Sm 64 bit rd pair ret(%d)\n", ret);
+ return ret;
+ }
+ sml_ctr_htonl_n((u32 *)&rsp, 4);
+ *value1 = ((u64)rsp.bs_bp64_rsp.val1_h << 32) | rsp.bs_bp64_rsp.val1_l;
+ *value2 = ((u64)rsp.bs_bp64_rsp.val2_h << 32) | rsp.bs_bp64_rsp.val2_l;
+
+ return 0;
+}
+
+/**
+ * hifc_sm_ctr_wr64_pair - big pair 128 counter write
+ * @hwdev: the pointer to hw device
+ * @node: the node id
+ * @ctr_id: counter id
+ * @instance: instance value
+ * @value1: write counter value
+ * @value2: write counter value
+ * Return: 0 - success, negative - failure
+ */
+int hifc_sm_ctr_wr64_pair(void *hwdev, u8 node, u8 instance,
+ u32 ctr_id, u64 value1, u64 value2)
+{
+ struct chipif_sml_ctr_wr_req_s req;
+ struct chipif_sml_ctr_wr_rsp_s rsp;
+
+ /* pair pattern ctr_id must be even number */
+ if (!hwdev || (0 != (ctr_id & 0x1))) {
+ pr_err("Handle is NULL or ctr_id(%d) is odd number for write 64 bit pair\n",
+ ctr_id);
+ return -EFAULT;
+ }
+
+ hifc_sml_ctr_write_build_req(&req, instance, CHIPIF_SM_CTR_OP_WRITE,
+ CHIPIF_NOACK, ctr_id, value1, value2);
+ return hifc_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req), (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+}
+
+int hifc_api_csr_rd32(void *hwdev, u8 dest, u32 addr, u32 *val)
+{
+ struct hifc_csr_request_api_data api_data = {0};
+ u32 csr_val = 0;
+ u16 in_size = sizeof(api_data);
+ int ret;
+
+ if (!hwdev || !val)
+ return -EFAULT;
+
+ memset(&api_data, 0, sizeof(struct hifc_csr_request_api_data));
+ api_data.dw0 = 0;
+ api_data.dw1.bits.operation_id = HIFC_CSR_OPERATION_READ_CSR;
+ api_data.dw1.bits.need_response = HIFC_CSR_NEED_RESP_DATA;
+ api_data.dw1.bits.data_size = HIFC_CSR_DATA_SZ_32;
+ api_data.dw1.val32 = cpu_to_be32(api_data.dw1.val32);
+ api_data.dw2.bits.csr_addr = addr;
+ api_data.dw2.val32 = cpu_to_be32(api_data.dw2.val32);
+
+ ret = hifc_api_cmd_read_ack(hwdev, dest, (u8 *)(&api_data),
+ in_size, &csr_val, 4);
+ if (ret) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Read 32 bit csr fail, dest %d addr 0x%x, ret: 0x%x\n",
+ dest, addr, ret);
+ return ret;
+ }
+
+ *val = csr_val;
+
+ return 0;
+}
+
+int hifc_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val)
+{
+ struct hifc_csr_request_api_data api_data;
+ u16 in_size = sizeof(api_data);
+ int ret;
+
+ if (!hwdev)
+ return -EFAULT;
+
+ memset(&api_data, 0, sizeof(struct hifc_csr_request_api_data));
+ api_data.dw1.bits.operation_id = HIFC_CSR_OPERATION_WRITE_CSR;
+ api_data.dw1.bits.need_response = HIFC_CSR_NO_RESP_DATA;
+ api_data.dw1.bits.data_size = HIFC_CSR_DATA_SZ_32;
+ api_data.dw1.val32 = cpu_to_be32(api_data.dw1.val32);
+ api_data.dw2.bits.csr_addr = addr;
+ api_data.dw2.val32 = cpu_to_be32(api_data.dw2.val32);
+ api_data.csr_write_data_h = 0xffffffff;
+ api_data.csr_write_data_l = val;
+
+ ret = hifc_api_cmd_write_nack(hwdev, dest, (u8 *)(&api_data), in_size);
+ if (ret) {
+ sdk_err(((struct hifc_hwdev *)hwdev)->dev_hdl,
+ "Write 32 bit csr fail! dest %d addr 0x%x val 0x%x\n",
+ dest, addr, val);
+ return ret;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/scsi/huawei/hifc/hifc_sml.h b/drivers/scsi/huawei/hifc/hifc_sml.h
new file mode 100644
index 000000000000..9fe2088f48a1
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_sml.h
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef __CHIPIF_SML_COUNTER_H__
+#define __CHIPIF_SML_COUNTER_H__
+
+#define CHIPIF_FUNC_PF 0
+#define CHIPIF_FUNC_VF 1
+#define CHIPIF_FUNC_PPF 2
+
+#define CHIPIF_ACK 1
+#define CHIPIF_NOACK 0
+
+#define CHIPIF_SM_CTR_OP_READ 0x2
+#define CHIPIF_SM_CTR_OP_READ_CLEAR 0x6
+#define CHIPIF_SM_CTR_OP_WRITE 0x3
+
+#define SMALL_CNT_READ_RSP_SIZE 16
+
+/* request head */
+union chipif_sml_ctr_req_head_u {
+ struct {
+ u32 pad:15;
+ u32 ack:1;
+ u32 op_id:5;
+ u32 instance:6;
+ u32 src:5;
+ } bs;
+
+ u32 value;
+};
+
+/* counter read request struct */
+struct chipif_sml_ctr_rd_req_s {
+ u32 extra;
+ union chipif_sml_ctr_req_head_u head;
+ u32 ctr_id;
+ u32 initial;
+ u32 pad;
+};
+
+/* counter read response union */
+union ctr_rd_rsp_u {
+ struct {
+ u32 value1:16;
+ u32 pad0:16;
+ u32 pad1[3];
+ } bs_ss16_rsp;
+
+ struct {
+ u32 value1;
+ u32 pad[3];
+ } bs_ss32_rsp;
+
+ struct {
+ u32 value1:20;
+ u32 pad0:12;
+ u32 value2:12;
+ u32 pad1:20;
+ u32 pad2[2];
+ } bs_sp_rsp;
+
+ struct {
+ u32 value1;
+ u32 value2;
+ u32 pad[2];
+ } bs_bs64_rsp;
+
+ struct {
+ u32 val1_h;
+ u32 val1_l;
+ u32 val2_h;
+ u32 val2_l;
+ } bs_bp64_rsp;
+
+};
+
+/* resopnse head */
+union sml_ctr_rsp_head_u {
+ struct {
+ u32 pad:30; /* reserve */
+ u32 code:2; /* error code */
+ } bs;
+
+ u32 value;
+};
+
+/* counter write request struct */
+struct chipif_sml_ctr_wr_req_s {
+ u32 extra;
+ union chipif_sml_ctr_req_head_u head;
+ u32 ctr_id;
+ u32 rsv1;
+ u32 rsv2;
+ u32 value1_h;
+ u32 value1_l;
+ u32 value2_h;
+ u32 value2_l;
+};
+
+/* counter write response struct */
+struct chipif_sml_ctr_wr_rsp_s {
+ union sml_ctr_rsp_head_u head;
+ u32 pad[3];
+};
+
+enum HIFC_CSR_API_DATA_OPERATION_ID {
+ HIFC_CSR_OPERATION_WRITE_CSR = 0x1E,
+ HIFC_CSR_OPERATION_READ_CSR = 0x1F
+};
+
+enum HIFC_CSR_API_DATA_NEED_RESPONSE_DATA {
+ HIFC_CSR_NO_RESP_DATA = 0,
+ HIFC_CSR_NEED_RESP_DATA = 1
+};
+
+enum HIFC_CSR_API_DATA_DATA_SIZE {
+ HIFC_CSR_DATA_SZ_32 = 0,
+ HIFC_CSR_DATA_SZ_64 = 1
+};
+
+struct hifc_csr_request_api_data {
+ u32 dw0;
+
+ union {
+ struct {
+ u32 reserved1:13;
+ /* this field indicates the write/read data size:
+ * 2'b00: 32 bits
+ * 2'b01: 64 bits
+ * 2'b10~2'b11:reserved
+ */
+ u32 data_size:2;
+ /* this field indicates that requestor expect receive a
+ * response data or not.
+ * 1'b0: expect not to receive a response data.
+ * 1'b1: expect to receive a response data.
+ */
+ u32 need_response:1;
+ /* this field indicates the operation that the requestor
+ * expected.
+ * 5'b1_1110: write value to csr space.
+ * 5'b1_1111: read register from csr space.
+ */
+ u32 operation_id:5;
+ u32 reserved2:6;
+ /* this field specifies the Src node ID for this API
+ * request message.
+ */
+ u32 src_node_id:5;
+ } bits;
+
+ u32 val32;
+ } dw1;
+
+ union {
+ struct {
+ /* it specifies the CSR address. */
+ u32 csr_addr:26;
+ u32 reserved3:6;
+ } bits;
+
+ u32 val32;
+ } dw2;
+
+ /* if data_size=2'b01, it is high 32 bits of write data. else, it is
+ * 32'hFFFF_FFFF.
+ */
+ u32 csr_write_data_h;
+ /* the low 32 bits of write data. */
+ u32 csr_write_data_l;
+};
+
+int hifc_sm_ctr_rd32(void *hwdev, u8 node, u8 instance, u32 ctr_id, u32 *value);
+int hifc_sm_ctr_rd64(void *hwdev, u8 node, u8 instance, u32 ctr_id, u64 *value);
+int hifc_sm_ctr_rd64_pair(void *hwdev, u8 node, u8 instance,
+ u32 ctr_id, u64 *value1, u64 *value2);
+
+#endif
+
diff --git a/drivers/scsi/huawei/hifc/hifc_wq.c b/drivers/scsi/huawei/hifc/hifc_wq.c
new file mode 100644
index 000000000000..4e926d140b2c
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_wq.c
@@ -0,0 +1,624 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "hifc_knl_adp.h"
+#include "hifc_hw.h"
+#include "hifc_hwif.h"
+#include "hifc_wq.h"
+
+#define WQS_MAX_NUM_BLOCKS 128
+#define WQS_FREE_BLOCKS_SIZE(wqs) (WQS_MAX_NUM_BLOCKS * \
+ sizeof((wqs)->free_blocks[0]))
+
+static void wqs_return_block(struct hifc_wqs *wqs, u32 page_idx, u32 block_idx)
+{
+ u32 pos;
+
+ spin_lock(&wqs->alloc_blocks_lock);
+
+ wqs->num_free_blks++;
+
+ pos = wqs->return_blk_pos++;
+ pos &= WQS_MAX_NUM_BLOCKS - 1;
+
+ wqs->free_blocks[pos].page_idx = page_idx;
+ wqs->free_blocks[pos].block_idx = block_idx;
+
+ spin_unlock(&wqs->alloc_blocks_lock);
+}
+
+static int wqs_next_block(struct hifc_wqs *wqs, u32 *page_idx,
+ u32 *block_idx)
+{
+ u32 pos;
+
+ spin_lock(&wqs->alloc_blocks_lock);
+
+ if (wqs->num_free_blks <= 0) {
+ spin_unlock(&wqs->alloc_blocks_lock);
+ return -ENOMEM;
+ }
+ wqs->num_free_blks--;
+
+ pos = wqs->alloc_blk_pos++;
+ pos &= WQS_MAX_NUM_BLOCKS - 1;
+
+ *page_idx = wqs->free_blocks[pos].page_idx;
+ *block_idx = wqs->free_blocks[pos].block_idx;
+
+ wqs->free_blocks[pos].page_idx = 0xFFFFFFFF;
+ wqs->free_blocks[pos].block_idx = 0xFFFFFFFF;
+
+ spin_unlock(&wqs->alloc_blocks_lock);
+
+ return 0;
+}
+
+static int queue_alloc_page(void *handle, u64 **vaddr, u64 *paddr,
+ u64 **shadow_vaddr, u64 page_sz)
+{
+ dma_addr_t dma_addr = 0;
+
+ *vaddr = dma_zalloc_coherent(handle, page_sz, &dma_addr,
+ GFP_KERNEL);
+ if (!*vaddr) {
+ sdk_err(handle, "Failed to allocate dma to wqs page\n");
+ return -ENOMEM;
+ }
+
+ if (!ADDR_4K_ALIGNED(dma_addr)) {
+ sdk_err(handle, "Cla is not 4k aligned!\n");
+ goto shadow_vaddr_err;
+ }
+
+ *paddr = (u64)dma_addr;
+
+ /* use vzalloc for big mem, shadow_vaddr only used at initialization */
+ *shadow_vaddr = vzalloc(page_sz);
+ if (!*shadow_vaddr) {
+ sdk_err(handle, "Failed to allocate shadow page vaddr\n");
+ goto shadow_vaddr_err;
+ }
+
+ return 0;
+
+shadow_vaddr_err:
+ dma_free_coherent(handle, page_sz, *vaddr, dma_addr);
+ return -ENOMEM;
+}
+
+static int wqs_allocate_page(struct hifc_wqs *wqs, u32 page_idx)
+{
+ return queue_alloc_page(wqs->dev_hdl, &wqs->page_vaddr[page_idx],
+ &wqs->page_paddr[page_idx],
+ &wqs->shadow_page_vaddr[page_idx],
+ WQS_PAGE_SIZE);
+}
+
+static void wqs_free_page(struct hifc_wqs *wqs, u32 page_idx)
+{
+ dma_free_coherent(wqs->dev_hdl, WQS_PAGE_SIZE,
+ wqs->page_vaddr[page_idx],
+ (dma_addr_t)wqs->page_paddr[page_idx]);
+ vfree(wqs->shadow_page_vaddr[page_idx]);
+}
+
+static int cmdq_allocate_page(struct hifc_cmdq_pages *cmdq_pages)
+{
+ return queue_alloc_page(cmdq_pages->dev_hdl,
+ &cmdq_pages->cmdq_page_vaddr,
+ &cmdq_pages->cmdq_page_paddr,
+ &cmdq_pages->cmdq_shadow_page_vaddr,
+ CMDQ_PAGE_SIZE);
+}
+
+static void cmdq_free_page(struct hifc_cmdq_pages *cmdq_pages)
+{
+ dma_free_coherent(cmdq_pages->dev_hdl, CMDQ_PAGE_SIZE,
+ cmdq_pages->cmdq_page_vaddr,
+ (dma_addr_t)cmdq_pages->cmdq_page_paddr);
+ vfree(cmdq_pages->cmdq_shadow_page_vaddr);
+}
+
+static int alloc_wqes_shadow(struct hifc_wq *wq)
+{
+ u64 size;
+
+ /* if wq->max_wqe_size == 0, we don't need to alloc shadow */
+ if (wq->max_wqe_size <= wq->wqebb_size)
+ return 0;
+
+ size = (u64)wq->num_q_pages * wq->max_wqe_size;
+ wq->shadow_wqe = kzalloc(size, GFP_KERNEL);
+ if (!wq->shadow_wqe) {
+ pr_err("Failed to allocate shadow wqe\n");
+ return -ENOMEM;
+ }
+
+ size = wq->num_q_pages * sizeof(wq->prod_idx);
+ wq->shadow_idx = kzalloc(size, GFP_KERNEL);
+ if (!wq->shadow_idx) {
+ pr_err("Failed to allocate shadow index\n");
+ goto shadow_idx_err;
+ }
+
+ return 0;
+
+shadow_idx_err:
+ kfree(wq->shadow_wqe);
+ return -ENOMEM;
+}
+
+static void free_wqes_shadow(struct hifc_wq *wq)
+{
+ if (wq->max_wqe_size <= wq->wqebb_size)
+ return;
+
+ kfree(wq->shadow_idx);
+ kfree(wq->shadow_wqe);
+}
+
+static void free_wq_pages(void *handle, struct hifc_wq *wq,
+ u32 num_q_pages)
+{
+ u32 i;
+
+ for (i = 0; i < num_q_pages; i++)
+ hifc_dma_free_coherent_align(handle, &wq->mem_align[i]);
+
+ free_wqes_shadow(wq);
+
+ wq->block_vaddr = NULL;
+ wq->shadow_block_vaddr = NULL;
+
+ kfree(wq->mem_align);
+}
+
+static int alloc_wq_pages(void *dev_hdl, struct hifc_wq *wq)
+{
+ struct hifc_dma_addr_align *mem_align;
+ u64 *vaddr, *paddr;
+ u32 i, num_q_pages;
+ int err;
+
+ vaddr = wq->shadow_block_vaddr;
+ paddr = wq->block_vaddr;
+
+ num_q_pages = ALIGN(WQ_SIZE(wq), wq->wq_page_size) / wq->wq_page_size;
+ if (num_q_pages > WQ_MAX_PAGES) {
+ sdk_err(dev_hdl, "Number(%d) wq pages exceeds the limit\n",
+ num_q_pages);
+ return -EINVAL;
+ }
+
+ if (num_q_pages & (num_q_pages - 1)) {
+ sdk_err(dev_hdl, "Wq num(%d) q pages must be power of 2\n",
+ num_q_pages);
+ return -EINVAL;
+ }
+
+ wq->num_q_pages = num_q_pages;
+
+ err = alloc_wqes_shadow(wq);
+ if (err) {
+ sdk_err(dev_hdl, "Failed to allocate wqe shadow\n");
+ return err;
+ }
+
+ wq->mem_align = kcalloc(wq->num_q_pages, sizeof(*wq->mem_align),
+ GFP_KERNEL);
+ if (!wq->mem_align) {
+ sdk_err(dev_hdl, "Failed to allocate mem_align\n");
+ free_wqes_shadow(wq);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < num_q_pages; i++) {
+ mem_align = &wq->mem_align[i];
+ err = hifc_dma_zalloc_coherent_align(dev_hdl, wq->wq_page_size,
+ wq->wq_page_size,
+ GFP_KERNEL, mem_align);
+ if (err) {
+ sdk_err(dev_hdl, "Failed to allocate wq page\n");
+ goto alloc_wq_pages_err;
+ }
+
+ *paddr = cpu_to_be64(mem_align->align_paddr);
+ *vaddr = (u64)mem_align->align_vaddr;
+
+ paddr++;
+ vaddr++;
+ }
+
+ return 0;
+
+alloc_wq_pages_err:
+ free_wq_pages(dev_hdl, wq, i);
+
+ return -ENOMEM;
+}
+
+int hifc_wq_allocate(struct hifc_wqs *wqs, struct hifc_wq *wq,
+ u32 wqebb_size, u32 wq_page_size, u16 q_depth,
+ u32 max_wqe_size)
+{
+ u32 num_wqebbs_per_page;
+ int err;
+
+ if (wqebb_size == 0) {
+ sdk_err(wqs->dev_hdl, "Wqebb_size must be >0\n");
+ return -EINVAL;
+ }
+
+ if (q_depth & (q_depth - 1)) {
+ sdk_err(wqs->dev_hdl, "Wq q_depth(%d) isn't power of 2\n",
+ q_depth);
+ return -EINVAL;
+ }
+
+ if (wq_page_size & (wq_page_size - 1)) {
+ sdk_err(wqs->dev_hdl, "Wq page_size(%d) isn't power of 2\n",
+ wq_page_size);
+ return -EINVAL;
+ }
+
+ num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) / wqebb_size;
+
+ if (num_wqebbs_per_page & (num_wqebbs_per_page - 1)) {
+ sdk_err(wqs->dev_hdl, "Num(%d) wqebbs per page isn't power of 2\n",
+ num_wqebbs_per_page);
+ return -EINVAL;
+ }
+
+ err = wqs_next_block(wqs, &wq->page_idx, &wq->block_idx);
+ if (err) {
+ sdk_err(wqs->dev_hdl, "Failed to get free wqs next block\n");
+ return err;
+ }
+
+ wq->wqebb_size = wqebb_size;
+ wq->wq_page_size = wq_page_size;
+ wq->q_depth = q_depth;
+ wq->max_wqe_size = max_wqe_size;
+ wq->num_wqebbs_per_page = num_wqebbs_per_page;
+
+ wq->wqebbs_per_page_shift = (u32)ilog2(num_wqebbs_per_page);
+
+ wq->block_vaddr = WQ_BASE_VADDR(wqs, wq);
+ wq->shadow_block_vaddr = WQ_BASE_ADDR(wqs, wq);
+ wq->block_paddr = WQ_BASE_PADDR(wqs, wq);
+
+ err = alloc_wq_pages(wqs->dev_hdl, wq);
+ if (err) {
+ sdk_err(wqs->dev_hdl, "Failed to allocate wq pages\n");
+ goto alloc_wq_pages_err;
+ }
+
+ atomic_set(&wq->delta, q_depth);
+ wq->cons_idx = 0;
+ wq->prod_idx = 0;
+ wq->mask = q_depth - 1;
+
+ return 0;
+
+alloc_wq_pages_err:
+ wqs_return_block(wqs, wq->page_idx, wq->block_idx);
+ return err;
+}
+
+void hifc_wq_free(struct hifc_wqs *wqs, struct hifc_wq *wq)
+{
+ free_wq_pages(wqs->dev_hdl, wq, wq->num_q_pages);
+
+ wqs_return_block(wqs, wq->page_idx, wq->block_idx);
+}
+
+static void init_wqs_blocks_arr(struct hifc_wqs *wqs)
+{
+ u32 page_idx, blk_idx, pos = 0;
+
+ for (page_idx = 0; page_idx < wqs->num_pages; page_idx++) {
+ for (blk_idx = 0; blk_idx < WQS_BLOCKS_PER_PAGE; blk_idx++) {
+ wqs->free_blocks[pos].page_idx = page_idx;
+ wqs->free_blocks[pos].block_idx = blk_idx;
+ pos++;
+ }
+ }
+
+ wqs->alloc_blk_pos = 0;
+ wqs->return_blk_pos = 0;
+ wqs->num_free_blks = WQS_MAX_NUM_BLOCKS;
+ spin_lock_init(&wqs->alloc_blocks_lock);
+}
+
+void hifc_wq_wqe_pg_clear(struct hifc_wq *wq)
+{
+ u64 *block_vaddr;
+ u32 pg_idx;
+
+ block_vaddr = wq->shadow_block_vaddr;
+
+ atomic_set(&wq->delta, wq->q_depth);
+ wq->cons_idx = 0;
+ wq->prod_idx = 0;
+
+ for (pg_idx = 0; pg_idx < wq->num_q_pages; pg_idx++)
+ memset((void *)(*(block_vaddr + pg_idx)), 0, wq->wq_page_size);
+}
+
+int hifc_cmdq_alloc(struct hifc_cmdq_pages *cmdq_pages,
+ struct hifc_wq *wq, void *dev_hdl,
+ int cmdq_blocks, u32 wq_page_size, u32 wqebb_size,
+ u16 q_depth, u32 max_wqe_size)
+{
+ int i, j, err = -ENOMEM;
+
+ if (q_depth & (q_depth - 1)) {
+ sdk_err(dev_hdl, "Cmdq q_depth(%d) isn't power of 2\n",
+ q_depth);
+ return -EINVAL;
+ }
+
+ cmdq_pages->dev_hdl = dev_hdl;
+
+ err = cmdq_allocate_page(cmdq_pages);
+ if (err) {
+ sdk_err(dev_hdl, "Failed to allocate CMDQ page\n");
+ return err;
+ }
+
+ for (i = 0; i < cmdq_blocks; i++) {
+ wq[i].page_idx = 0;
+ wq[i].block_idx = (u32)i;
+ wq[i].wqebb_size = wqebb_size;
+ wq[i].wq_page_size = wq_page_size;
+ wq[i].q_depth = q_depth;
+ wq[i].max_wqe_size = max_wqe_size;
+ wq[i].num_wqebbs_per_page =
+ ALIGN(wq_page_size, wqebb_size) / wqebb_size;
+
+ wq[i].wqebbs_per_page_shift =
+ (u32)ilog2(wq[i].num_wqebbs_per_page);
+
+ wq[i].block_vaddr = CMDQ_BASE_VADDR(cmdq_pages, &wq[i]);
+ wq[i].shadow_block_vaddr = CMDQ_BASE_ADDR(cmdq_pages, &wq[i]);
+ wq[i].block_paddr = CMDQ_BASE_PADDR(cmdq_pages, &wq[i]);
+
+ err = alloc_wq_pages(cmdq_pages->dev_hdl, &wq[i]);
+ if (err) {
+ sdk_err(dev_hdl, "Failed to alloc CMDQ blocks\n");
+ goto cmdq_block_err;
+ }
+
+ atomic_set(&wq[i].delta, q_depth);
+ wq[i].cons_idx = 0;
+ wq[i].prod_idx = 0;
+ wq[i].mask = q_depth - 1;
+ }
+
+ return 0;
+
+cmdq_block_err:
+ for (j = 0; j < i; j++)
+ free_wq_pages(cmdq_pages->dev_hdl, &wq[j], wq[j].num_q_pages);
+
+ cmdq_free_page(cmdq_pages);
+ return err;
+}
+
+void hifc_cmdq_free(struct hifc_cmdq_pages *cmdq_pages,
+ struct hifc_wq *wq, int cmdq_blocks)
+{
+ int i;
+
+ for (i = 0; i < cmdq_blocks; i++)
+ free_wq_pages(cmdq_pages->dev_hdl, &wq[i], wq[i].num_q_pages);
+
+ cmdq_free_page(cmdq_pages);
+}
+
+static int alloc_page_addr(struct hifc_wqs *wqs)
+{
+ u64 size = wqs->num_pages * sizeof(*wqs->page_paddr);
+
+ wqs->page_paddr = kzalloc(size, GFP_KERNEL);
+ if (!wqs->page_paddr)
+ return -ENOMEM;
+
+ size = wqs->num_pages * sizeof(*wqs->page_vaddr);
+ wqs->page_vaddr = kzalloc(size, GFP_KERNEL);
+ if (!wqs->page_vaddr)
+ goto page_vaddr_err;
+
+ size = wqs->num_pages * sizeof(*wqs->shadow_page_vaddr);
+ wqs->shadow_page_vaddr = kzalloc(size, GFP_KERNEL);
+ if (!wqs->shadow_page_vaddr)
+ goto page_shadow_vaddr_err;
+
+ return 0;
+
+page_shadow_vaddr_err:
+ kfree(wqs->page_vaddr);
+
+page_vaddr_err:
+ kfree(wqs->page_paddr);
+ return -ENOMEM;
+}
+
+static void free_page_addr(struct hifc_wqs *wqs)
+{
+ kfree(wqs->shadow_page_vaddr);
+ kfree(wqs->page_vaddr);
+ kfree(wqs->page_paddr);
+}
+
+int hifc_wqs_alloc(struct hifc_wqs *wqs, int num_wqs, void *dev_hdl)
+{
+ u32 i, page_idx;
+ int err;
+
+ wqs->dev_hdl = dev_hdl;
+ wqs->num_pages = WQ_NUM_PAGES(num_wqs);
+
+ if (alloc_page_addr(wqs)) {
+ sdk_err(dev_hdl, "Failed to allocate mem for page addresses\n");
+ return -ENOMEM;
+ }
+
+ for (page_idx = 0; page_idx < wqs->num_pages; page_idx++) {
+ err = wqs_allocate_page(wqs, page_idx);
+ if (err) {
+ sdk_err(dev_hdl, "Failed wq page allocation\n");
+ goto wq_allocate_page_err;
+ }
+ }
+
+ wqs->free_blocks = kzalloc(WQS_FREE_BLOCKS_SIZE(wqs), GFP_KERNEL);
+ if (!wqs->free_blocks) {
+ err = -ENOMEM;
+ goto alloc_blocks_err;
+ }
+
+ init_wqs_blocks_arr(wqs);
+ return 0;
+
+alloc_blocks_err:
+wq_allocate_page_err:
+ for (i = 0; i < page_idx; i++)
+ wqs_free_page(wqs, i);
+
+ free_page_addr(wqs);
+ return err;
+}
+
+void hifc_wqs_free(struct hifc_wqs *wqs)
+{
+ u32 page_idx;
+
+ for (page_idx = 0; page_idx < wqs->num_pages; page_idx++)
+ wqs_free_page(wqs, page_idx);
+
+ free_page_addr(wqs);
+ kfree(wqs->free_blocks);
+}
+
+static void copy_wqe_to_shadow(struct hifc_wq *wq, void *shadow_addr,
+ int num_wqebbs, u16 prod_idx)
+{
+ u8 *shadow_wqebb_addr, *wqe_page_addr, *wqebb_addr;
+ u32 i, offset;
+ u16 idx;
+
+ for (i = 0; i < (u32)num_wqebbs; i++) {
+ offset = i * wq->wqebb_size;
+ shadow_wqebb_addr = (u8 *)shadow_addr + offset;
+
+ idx = MASKED_WQE_IDX(wq, prod_idx + i);
+ wqe_page_addr = WQ_PAGE_ADDR(wq, idx);
+ wqebb_addr = wqe_page_addr +
+ WQE_PAGE_OFF(wq, MASKED_WQE_IDX(wq, idx));
+
+ memcpy(shadow_wqebb_addr, wqebb_addr, wq->wqebb_size);
+ }
+}
+
+void *hifc_get_wqebb_addr(struct hifc_wq *wq, u16 index)
+{
+ return WQ_PAGE_ADDR(wq, index) + WQE_PAGE_OFF(wq, index);
+}
+
+u64 hifc_get_first_wqe_page_addr(struct hifc_wq *wq)
+{
+ return be64_to_cpu(*wq->block_vaddr);
+}
+
+void *hifc_get_wqe(struct hifc_wq *wq, int num_wqebbs, u16 *prod_idx)
+{
+ u32 curr_pg, end_pg;
+ u16 curr_prod_idx, end_prod_idx;
+
+ if (atomic_sub_return(num_wqebbs, &wq->delta) < 0) {
+ atomic_add(num_wqebbs, &wq->delta);
+ return NULL;
+ }
+
+ /* use original cur_pi and end_pi, no need queue depth mask as
+ * WQE_PAGE_NUM will do num_queue_pages mask
+ */
+ curr_prod_idx = (u16)wq->prod_idx;
+ wq->prod_idx += num_wqebbs;
+
+ /* end prod index should points to the last wqebb of wqe,
+ * therefore minus 1
+ */
+ end_prod_idx = (u16)wq->prod_idx - 1;
+
+ curr_pg = WQE_PAGE_NUM(wq, curr_prod_idx);
+ end_pg = WQE_PAGE_NUM(wq, end_prod_idx);
+
+ *prod_idx = MASKED_WQE_IDX(wq, curr_prod_idx);
+
+ /* If we only have one page, still need to get shadown wqe when
+ * wqe rolling-over page
+ */
+ if (curr_pg != end_pg || MASKED_WQE_IDX(wq, end_prod_idx) < *prod_idx) {
+ u32 offset = curr_pg * wq->max_wqe_size;
+ u8 *shadow_addr = wq->shadow_wqe + offset;
+
+ wq->shadow_idx[curr_pg] = *prod_idx;
+ return shadow_addr;
+ }
+
+ return WQ_PAGE_ADDR(wq, *prod_idx) + WQE_PAGE_OFF(wq, *prod_idx);
+}
+
+void hifc_put_wqe(struct hifc_wq *wq, int num_wqebbs)
+{
+ atomic_add(num_wqebbs, &wq->delta);
+ wq->cons_idx += num_wqebbs;
+}
+
+void *hifc_read_wqe(struct hifc_wq *wq, int num_wqebbs, u16 *cons_idx)
+{
+ u32 curr_pg, end_pg;
+ u16 curr_cons_idx, end_cons_idx;
+
+ if ((atomic_read(&wq->delta) + num_wqebbs) > wq->q_depth)
+ return NULL;
+
+ curr_cons_idx = (u16)wq->cons_idx;
+
+ curr_cons_idx = MASKED_WQE_IDX(wq, curr_cons_idx);
+ end_cons_idx = MASKED_WQE_IDX(wq, curr_cons_idx + num_wqebbs - 1);
+
+ curr_pg = WQE_PAGE_NUM(wq, curr_cons_idx);
+ end_pg = WQE_PAGE_NUM(wq, end_cons_idx);
+
+ *cons_idx = curr_cons_idx;
+
+ if (curr_pg != end_pg) {
+ u32 offset = curr_pg * wq->max_wqe_size;
+ u8 *shadow_addr = wq->shadow_wqe + offset;
+
+ copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *cons_idx);
+
+ return shadow_addr;
+ }
+
+ return WQ_PAGE_ADDR(wq, *cons_idx) + WQE_PAGE_OFF(wq, *cons_idx);
+}
diff --git a/drivers/scsi/huawei/hifc/hifc_wq.h b/drivers/scsi/huawei/hifc/hifc_wq.h
new file mode 100644
index 000000000000..207d54191afa
--- /dev/null
+++ b/drivers/scsi/huawei/hifc/hifc_wq.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Huawei Hifc PCI Express Linux driver
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ *
+ */
+
+#ifndef HIFC_WQ_H
+#define HIFC_WQ_H
+
+#define WQS_BLOCKS_PER_PAGE 4
+#define WQ_SIZE(wq) (u32)((u64)(wq)->q_depth * (wq)->wqebb_size)
+
+#define WQE_PAGE_NUM(wq, idx) (((idx) >> ((wq)->wqebbs_per_page_shift)) & \
+ ((wq)->num_q_pages - 1))
+
+#define WQE_PAGE_OFF(wq, idx) ((u64)((wq)->wqebb_size) * \
+ ((idx) & ((wq)->num_wqebbs_per_page - 1)))
+
+#define WQ_PAGE_ADDR_SIZE sizeof(u64)
+#define WQ_PAGE_ADDR_SIZE_SHIFT 3
+#define WQ_PAGE_ADDR(wq, idx) \
+ (u8 *)(*(u64 *)((u64)((wq)->shadow_block_vaddr) + \
+ (WQE_PAGE_NUM(wq, idx) << WQ_PAGE_ADDR_SIZE_SHIFT)))
+
+#define WQ_BLOCK_SIZE 4096UL
+#define WQS_PAGE_SIZE (WQS_BLOCKS_PER_PAGE * WQ_BLOCK_SIZE)
+#define WQ_MAX_PAGES (WQ_BLOCK_SIZE >> WQ_PAGE_ADDR_SIZE_SHIFT)
+
+#define CMDQ_BLOCKS_PER_PAGE 8
+#define CMDQ_BLOCK_SIZE 512UL
+#define CMDQ_PAGE_SIZE ALIGN((CMDQ_BLOCKS_PER_PAGE * \
+ CMDQ_BLOCK_SIZE), PAGE_SIZE)
+
+#define ADDR_4K_ALIGNED(addr) (((addr) & 0xfff) == 0)
+
+#define WQ_BASE_VADDR(wqs, wq) \
+ (u64 *)(((u64)((wqs)->page_vaddr[(wq)->page_idx])) \
+ + (wq)->block_idx * WQ_BLOCK_SIZE)
+
+#define WQ_BASE_PADDR(wqs, wq) (((wqs)->page_paddr[(wq)->page_idx]) \
+ + (u64)(wq)->block_idx * WQ_BLOCK_SIZE)
+
+#define WQ_BASE_ADDR(wqs, wq) \
+ (u64 *)(((u64)((wqs)->shadow_page_vaddr[(wq)->page_idx])) \
+ + (wq)->block_idx * WQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_VADDR(cmdq_pages, wq) \
+ (u64 *)(((u64)((cmdq_pages)->cmdq_page_vaddr)) \
+ + (wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_PADDR(cmdq_pages, wq) \
+ (((u64)((cmdq_pages)->cmdq_page_paddr)) \
+ + (u64)(wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_ADDR(cmdq_pages, wq) \
+ (u64 *)(((u64)((cmdq_pages)->cmdq_shadow_page_vaddr)) \
+ + (wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define MASKED_WQE_IDX(wq, idx) ((idx) & (wq)->mask)
+
+#define WQ_NUM_PAGES(num_wqs) \
+ (ALIGN((u32)num_wqs, WQS_BLOCKS_PER_PAGE) / WQS_BLOCKS_PER_PAGE)
+
+#define MAX_WQE_SIZE(max_sge, wqebb_size) \
+ ((max_sge <= 2) ? (wqebb_size) : \
+ ((ALIGN(((max_sge) - 2), 4) / 4 + 1) * (wqebb_size)))
+
+struct hifc_free_block {
+ u32 page_idx;
+ u32 block_idx;
+};
+
+struct hifc_wq {
+ /* The addresses are 64 bit in the HW */
+ u64 block_paddr;
+ u64 *shadow_block_vaddr;
+ u64 *block_vaddr;
+
+ u32 wqebb_size;
+ u32 wq_page_size;
+ u16 q_depth;
+ u32 max_wqe_size;
+ u32 num_wqebbs_per_page;
+
+ /* performance: replace mul/div as shift;
+ * num_wqebbs_per_page must be power of 2
+ */
+ u32 wqebbs_per_page_shift;
+ u32 page_idx;
+ u32 block_idx;
+
+ u32 num_q_pages;
+
+ struct hifc_dma_addr_align *mem_align;
+
+ int cons_idx;
+ int prod_idx;
+
+ atomic_t delta;
+ u16 mask;
+
+ u8 *shadow_wqe;
+ u16 *shadow_idx;
+};
+
+struct hifc_cmdq_pages {
+ /* The addresses are 64 bit in the HW */
+ u64 cmdq_page_paddr;
+ u64 *cmdq_page_vaddr;
+ u64 *cmdq_shadow_page_vaddr;
+
+ void *dev_hdl;
+};
+
+struct hifc_wqs {
+ /* The addresses are 64 bit in the HW */
+ u64 *page_paddr;
+ u64 **page_vaddr;
+ u64 **shadow_page_vaddr;
+
+ struct hifc_free_block *free_blocks;
+ u32 alloc_blk_pos;
+ u32 return_blk_pos;
+ int num_free_blks;
+
+ /* for allocate blocks */
+ spinlock_t alloc_blocks_lock;
+
+ u32 num_pages;
+
+ void *dev_hdl;
+};
+
+void hifc_wq_wqe_pg_clear(struct hifc_wq *wq);
+
+int hifc_cmdq_alloc(struct hifc_cmdq_pages *cmdq_pages,
+ struct hifc_wq *wq, void *dev_hdl,
+ int cmdq_blocks, u32 wq_page_size, u32 wqebb_size,
+ u16 q_depth, u32 max_wqe_size);
+
+void hifc_cmdq_free(struct hifc_cmdq_pages *cmdq_pages,
+ struct hifc_wq *wq, int cmdq_blocks);
+
+int hifc_wqs_alloc(struct hifc_wqs *wqs, int num_wqs, void *dev_hdl);
+
+void hifc_wqs_free(struct hifc_wqs *wqs);
+
+int hifc_wq_allocate(struct hifc_wqs *wqs, struct hifc_wq *wq,
+ u32 wqebb_size, u32 wq_page_size, u16 q_depth,
+ u32 max_wqe_size);
+
+void hifc_wq_free(struct hifc_wqs *wqs, struct hifc_wq *wq);
+
+void *hifc_get_wqebb_addr(struct hifc_wq *wq, u16 index);
+
+u64 hifc_get_first_wqe_page_addr(struct hifc_wq *wq);
+
+void *hifc_get_wqe(struct hifc_wq *wq, int num_wqebbs, u16 *prod_idx);
+
+void hifc_put_wqe(struct hifc_wq *wq, int num_wqebbs);
+
+void *hifc_read_wqe(struct hifc_wq *wq, int num_wqebbs, u16 *cons_idx);
+
+#endif
+
--
2.25.1
1
6
From: Peter Zijlstra <peterz(a)infradead.org>
mainline inclusion
from mainline-v5.2-rc1
commit dea2434c23c102b3e7d320849ec1cfeb432edb60
category:feature
bugzilla:NA
CVE:NA
-------------------
Write a comment explaining some of this..
Signed-off-by: Peter Zijlstra (Intel) <peterz(a)infradead.org>
Acked-by: Will Deacon <will.deacon(a)arm.com>
Cc: Andrew Morton <akpm(a)linux-foundation.org>
Cc: Andy Lutomirski <luto(a)kernel.org>
Cc: Aneesh Kumar K.V <aneesh.kumar(a)linux.vnet.ibm.com>
Cc: Borislav Petkov <bp(a)alien8.de>
Cc: Dave Hansen <dave.hansen(a)linux.intel.com>
Cc: H. Peter Anvin <hpa(a)zytor.com>
Cc: Linus Torvalds <torvalds(a)linux-foundation.org>
Cc: Nick Piggin <npiggin(a)gmail.com>
Cc: Peter Zijlstra <peterz(a)infradead.org>
Cc: Rik van Riel <riel(a)surriel.com>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Signed-off-by: Ingo Molnar <mingo(a)kernel.org>
Signed-off-by: Chen Jun <chenjun102(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/asm-generic/tlb.h | 119 +++++++++++++++++++++++++++++++++++++-
1 file changed, 116 insertions(+), 3 deletions(-)
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 147381aad7cc..632b1cdce357 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -22,6 +22,118 @@
#ifdef CONFIG_MMU
+/*
+ * Generic MMU-gather implementation.
+ *
+ * The mmu_gather data structure is used by the mm code to implement the
+ * correct and efficient ordering of freeing pages and TLB invalidations.
+ *
+ * This correct ordering is:
+ *
+ * 1) unhook page
+ * 2) TLB invalidate page
+ * 3) free page
+ *
+ * That is, we must never free a page before we have ensured there are no live
+ * translations left to it. Otherwise it might be possible to observe (or
+ * worse, change) the page content after it has been reused.
+ *
+ * The mmu_gather API consists of:
+ *
+ * - tlb_gather_mmu() / tlb_finish_mmu(); start and finish a mmu_gather
+ *
+ * Finish in particular will issue a (final) TLB invalidate and free
+ * all (remaining) queued pages.
+ *
+ * - tlb_start_vma() / tlb_end_vma(); marks the start / end of a VMA
+ *
+ * Defaults to flushing at tlb_end_vma() to reset the range; helps when
+ * there's large holes between the VMAs.
+ *
+ * - tlb_remove_page() / __tlb_remove_page()
+ * - tlb_remove_page_size() / __tlb_remove_page_size()
+ *
+ * __tlb_remove_page_size() is the basic primitive that queues a page for
+ * freeing. __tlb_remove_page() assumes PAGE_SIZE. Both will return a
+ * boolean indicating if the queue is (now) full and a call to
+ * tlb_flush_mmu() is required.
+ *
+ * tlb_remove_page() and tlb_remove_page_size() imply the call to
+ * tlb_flush_mmu() when required and has no return value.
+ *
+ * - tlb_remove_check_page_size_change()
+ *
+ * call before __tlb_remove_page*() to set the current page-size; implies a
+ * possible tlb_flush_mmu() call.
+ *
+ * - tlb_flush_mmu() / tlb_flush_mmu_tlbonly() / tlb_flush_mmu_free()
+ *
+ * tlb_flush_mmu_tlbonly() - does the TLB invalidate (and resets
+ * related state, like the range)
+ *
+ * tlb_flush_mmu_free() - frees the queued pages; make absolutely
+ * sure no additional tlb_remove_page()
+ * calls happen between _tlbonly() and this.
+ *
+ * tlb_flush_mmu() - the above two calls.
+ *
+ * - mmu_gather::fullmm
+ *
+ * A flag set by tlb_gather_mmu() to indicate we're going to free
+ * the entire mm; this allows a number of optimizations.
+ *
+ * - We can ignore tlb_{start,end}_vma(); because we don't
+ * care about ranges. Everything will be shot down.
+ *
+ * - (RISC) architectures that use ASIDs can cycle to a new ASID
+ * and delay the invalidation until ASID space runs out.
+ *
+ * - mmu_gather::need_flush_all
+ *
+ * A flag that can be set by the arch code if it wants to force
+ * flush the entire TLB irrespective of the range. For instance
+ * x86-PAE needs this when changing top-level entries.
+ *
+ * And requires the architecture to provide and implement tlb_flush().
+ *
+ * tlb_flush() may, in addition to the above mentioned mmu_gather fields, make
+ * use of:
+ *
+ * - mmu_gather::start / mmu_gather::end
+ *
+ * which provides the range that needs to be flushed to cover the pages to
+ * be freed.
+ *
+ * - mmu_gather::freed_tables
+ *
+ * set when we freed page table pages
+ *
+ * - tlb_get_unmap_shift() / tlb_get_unmap_size()
+ *
+ * returns the smallest TLB entry size unmapped in this range
+ *
+ * Additionally there are a few opt-in features:
+ *
+ * HAVE_RCU_TABLE_FREE
+ *
+ * This provides tlb_remove_table(), to be used instead of tlb_remove_page()
+ * for page directores (__p*_free_tlb()). This provides separate freeing of
+ * the page-table pages themselves in a semi-RCU fashion (see comment below).
+ * Useful if your architecture doesn't use IPIs for remote TLB invalidates
+ * and therefore doesn't naturally serialize with software page-table walkers.
+ *
+ * When used, an architecture is expected to provide __tlb_remove_table()
+ * which does the actual freeing of these pages.
+ *
+ * HAVE_RCU_TABLE_INVALIDATE
+ *
+ * This makes HAVE_RCU_TABLE_FREE call tlb_flush_mmu_tlbonly() before freeing
+ * the page-table pages. Required if you use HAVE_RCU_TABLE_FREE and your
+ * architecture uses the Linux page-tables natively.
+ *
+ */
+#define HAVE_GENERIC_MMU_GATHER
+
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
/*
* Semi RCU freeing of the page directories.
@@ -89,14 +201,17 @@ struct mmu_gather_batch {
*/
#define MAX_GATHER_BATCH_COUNT (10000UL/MAX_GATHER_BATCH)
-/* struct mmu_gather is an opaque type used by the mm code for passing around
+/*
+ * struct mmu_gather is an opaque type used by the mm code for passing around
* any data needed by arch specific code for tlb_remove_page.
*/
struct mmu_gather {
struct mm_struct *mm;
+
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch *batch;
#endif
+
unsigned long start;
unsigned long end;
/*
@@ -131,8 +246,6 @@ struct mmu_gather {
int page_size;
};
-#define HAVE_GENERIC_MMU_GATHER
-
void arch_tlb_gather_mmu(struct mmu_gather *tlb,
struct mm_struct *mm, unsigned long start, unsigned long end);
void tlb_flush_mmu(struct mmu_gather *tlb);
--
2.25.1
1
7
From: Yang Shi <shy828301(a)gmail.com>
mainline inclusion
from mainline-v5.9-rc4
commit 7867fd7cc44e63c6673cd0f8fea155456d34d0de
category: bugfix
bugzilla: 42216
CVE: NA
-------------------------------------------------
The syzbot reported the below use-after-free:
BUG: KASAN: use-after-free in madvise_willneed mm/madvise.c:293 [inline]
BUG: KASAN: use-after-free in madvise_vma mm/madvise.c:942 [inline]
BUG: KASAN: use-after-free in do_madvise.part.0+0x1c8b/0x1cf0 mm/madvise.c:1145
Read of size 8 at addr ffff8880a6163eb0 by task syz-executor.0/9996
CPU: 0 PID: 9996 Comm: syz-executor.0 Not tainted 5.9.0-rc1-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x18f/0x20d lib/dump_stack.c:118
print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:383
__kasan_report mm/kasan/report.c:513 [inline]
kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
madvise_willneed mm/madvise.c:293 [inline]
madvise_vma mm/madvise.c:942 [inline]
do_madvise.part.0+0x1c8b/0x1cf0 mm/madvise.c:1145
do_madvise mm/madvise.c:1169 [inline]
__do_sys_madvise mm/madvise.c:1171 [inline]
__se_sys_madvise mm/madvise.c:1169 [inline]
__x64_sys_madvise+0xd9/0x110 mm/madvise.c:1169
do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Allocated by task 9992:
kmem_cache_alloc+0x138/0x3a0 mm/slab.c:3482
vm_area_alloc+0x1c/0x110 kernel/fork.c:347
mmap_region+0x8e5/0x1780 mm/mmap.c:1743
do_mmap+0xcf9/0x11d0 mm/mmap.c:1545
vm_mmap_pgoff+0x195/0x200 mm/util.c:506
ksys_mmap_pgoff+0x43a/0x560 mm/mmap.c:1596
do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Freed by task 9992:
kmem_cache_free.part.0+0x67/0x1f0 mm/slab.c:3693
remove_vma+0x132/0x170 mm/mmap.c:184
remove_vma_list mm/mmap.c:2613 [inline]
__do_munmap+0x743/0x1170 mm/mmap.c:2869
do_munmap mm/mmap.c:2877 [inline]
mmap_region+0x257/0x1780 mm/mmap.c:1716
do_mmap+0xcf9/0x11d0 mm/mmap.c:1545
vm_mmap_pgoff+0x195/0x200 mm/util.c:506
ksys_mmap_pgoff+0x43a/0x560 mm/mmap.c:1596
do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
entry_SYSCALL_64_after_hwframe+0x44/0xa9
It is because vma is accessed after releasing mmap_lock, but someone
else acquired the mmap_lock and the vma is gone.
Releasing mmap_lock after accessing vma should fix the problem.
Fixes: 692fe62433d4c ("mm: Handle MADV_WILLNEED through vfs_fadvise()")
Reported-by: syzbot+b90df26038d1d5d85c97(a)syzkaller.appspotmail.com
Signed-off-by: Yang Shi <shy828301(a)gmail.com>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
Reviewed-by: Andrew Morton <akpm(a)linux-foundation.org>
Reviewed-by: Jan Kara <jack(a)suse.cz>
Cc: <stable(a)vger.kernel.org> [5.4+]
Link: https://lkml.kernel.org/r/20200816141204.162624-1-shy828301@gmail.com
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
Signed-off-by: Liu Shixin <liushixin2(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
mm/madvise.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/madvise.c b/mm/madvise.c
index 464282e24a30..1369e6d062bc 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -308,9 +308,9 @@ static long madvise_willneed(struct vm_area_struct *vma,
*/
*prev = NULL; /* tell sys_madvise we drop mmap_sem */
get_file(file);
- up_read(¤t->mm->mmap_sem);
offset = (loff_t)(start - vma->vm_start)
+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
+ up_read(¤t->mm->mmap_sem);
vfs_fadvise(file, offset, end - start, POSIX_FADV_WILLNEED);
fput(file);
down_read(¤t->mm->mmap_sem);
--
2.25.1
1
2
Alain Volmat (1):
cpufreq: sti-cpufreq: add stih418 support
Aleksandr Nogikh (1):
netem: fix zero division in tabledist
Alex Hung (1):
ACPI: video: use ACPI backlight for HP 635 Notebook
Alexander Sverdlin (2):
staging: octeon: repair "fixed-link" support
staging: octeon: Drop on uncorrectable alignment or FCS error
Alok Prasad (1):
RDMA/qedr: Fix memory leak in iWARP CM
Amit Cohen (1):
mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
Anand Jain (2):
btrfs: fix replace of seed device
btrfs: improve device scanning messages
Anant Thazhemadam (2):
net: 9p: initialize sun_server.sun_path to have addr's value only when
addr is valid
gfs2: add validation checks for size of superblock
Andrew Donnellan (1):
powerpc/rtas: Restrict RTAS requests from userspace
Andrew Gabbasov (1):
ravb: Fix bit fields checking in ravb_hwtstamp_get()
Andy Shevchenko (2):
device property: Keep secondary firmware node secondary by type
device property: Don't clear secondary pointer for shared primary
firmware node
Aneesh Kumar K.V (1):
powerpc/drmem: Make lmb_size 64 bit
Antonio Borneo (1):
drm/bridge/synopsys: dsi: add support for non-continuous HS clock
Arjun Roy (1):
tcp: Prevent low rmem stalls with SO_RCVLOWAT.
Ashish Sangwan (1):
NFS: fix nfs_path in case of a rename retry
Badhri Jagan Sridharan (1):
usb: typec: tcpm: During PR_SWAP, source caps should be sent only
after tSwapSourceStart
Bartosz Golaszewski (1):
rtc: rx8010: don't modify the global rtc ops
Ben Hutchings (1):
ACPI / extlog: Check for RDMSR failure
Chao Leng (1):
nvme-rdma: fix crash when connect rejected
Chao Yu (2):
f2fs: fix uninit-value in f2fs_lookup
f2fs: fix to check segment boundary during SIT page readahead
Chris Lew (1):
rpmsg: glink: Use complete_all for open states
Chris Wilson (1):
drm/i915: Force VT'd workarounds when running as a guest OS
Chuck Lever (1):
NFSD: Add missing NFSv2 .pc_func methods
Dan Carpenter (1):
memory: emif: Remove bogus debugfs error handling
Daniel W. S. Almeida (1):
media: uvcvideo: Fix dereference of out-of-bound list iterator
Darrick J. Wong (2):
xfs: fix realtime bitmap/summary file truncation when growing rt
volume
xfs: don't free rt blocks when we're doing a REMAP bunmapi call
Dave Airlie (1):
drm/ttm: fix eviction valuable range check.
Denis Efremov (1):
btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
Diana Craciun (1):
bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
Dinghao Liu (1):
ext4: fix error handling code in add_new_gdb
Douglas Anderson (2):
ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
Douglas Gilbert (1):
sgl_alloc_order: fix memory leak
Eric Biggers (7):
fscrypt: return -EXDEV for incompatible rename or link into encrypted
dir
fscrypt: clean up and improve dentry revalidation
fscrypt: fix race allowing rename() and link() of ciphertext dentries
fs, fscrypt: clear DCACHE_ENCRYPTED_NAME when unaliasing directory
fscrypt: only set dentry_operations on ciphertext dentries
fscrypt: fix race where ->lookup() marks plaintext dentry as
ciphertext
ext4: fix leaking sysfs kobject after failed mount
Fangzhi Zuo (1):
drm/amd/display: HDMI remote sink need mode validation for Linux
Filipe Manana (3):
btrfs: reschedule if necessary when logging directory items
btrfs: send, recompute reference path after orphanization of a
directory
btrfs: fix use-after-free on readahead extent after failure to create
it
Frank Wunderlich (1):
arm: dts: mt7623: add missing pause for switchport
Frederic Barrat (1):
cxl: Rework error message for incompatible slots
Geert Uytterhoeven (1):
ata: sata_rcar: Fix DMA boundary mask
Greg Kroah-Hartman (2):
Revert "block: ratelimit handle_bad_sector() message"
Linux 4.19.155
Gustavo A. R. Silva (1):
mtd: lpddr: Fix bad logic in print_drs_error
Hans Verkuil (2):
media: videodev2.h: RGB BT2020 and HSV are always full range
media: imx274: fix frame interval handling
Hans de Goede (1):
media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
Heiner Kallweit (1):
r8169: fix issue with forced threading in combination with shared
interrupts
Helge Deller (2):
scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
hil/parisc: Disable HIL driver when it gets stuck
Ian Abbott (1):
staging: comedi: cb_pcidas: Allow 2-channel commands for AO subdevice
Ido Schimmel (1):
mlxsw: core: Fix memory leak on module removal
Ilya Dryomov (1):
libceph: clear con->out_msg on Policy::stateful_server faults
Jamie Iles (1):
ACPI: debug: don't allow debugging when ACPI is disabled
Jan Kara (2):
ext4: Detect already used quota file early
udf: Fix memory leak when mounting
Jason Gerecke (1):
HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
Jason Gunthorpe (1):
RDMA/addr: Fix race with netevent_callback()/rdma_addr_cancel()
Jerome Brunet (1):
usb: cdc-acm: fix cooldown mechanism
Jia-Ju Bai (1):
p54: avoid accessing the data mapped to streaming DMA
Jiri Olsa (1):
perf python scripting: Fix printable strings in python3 scripts
Jiri Slaby (1):
x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10
compiled kernels
Jisheng Zhang (1):
arm64: berlin: Select DW_APB_TIMER_OF
Joel Stanley (1):
powerpc: Warn about use of smt_snooze_delay
Johannes Berg (1):
um: change sigio_spinlock to a mutex
John Ogness (1):
printk: reduce LOG_BUF_SHIFT range for H8300
Jonathan Cameron (5):
ACPI: Add out of bounds and numa_off protections to pxm_to_node()
iio:light:si1145: Fix timestamp alignment and prevent data leak.
iio:adc:ti-adc0832 Fix alignment issue with timestamp
iio:adc:ti-adc12138 Fix alignment issue with timestamp
iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
Josef Bacik (1):
btrfs: cleanup cow block on error
Josh Poimboeuf (1):
objtool: Support Clang non-section symbols in ORC generation
Juergen Gross (2):
x86/xen: disable Firmware First mode for correctable memory errors
xen/events: block rogue events for some time
Kim Phillips (3):
arch/x86/amd/ibs: Fix re-arming IBS Fetch
perf/x86/amd/ibs: Don't include randomized bits in get_ibs_op_count()
perf/x86/amd/ibs: Fix raw sample data accumulation
Krzysztof Kozlowski (8):
power: supply: bq27xxx: report "not charging" on all types
ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema
warnings
ARM: dts: s5pv210: move PMU node out of clock controller
ARM: dts: s5pv210: remove dedicated 'audio-subsystem' node
ia64: fix build error with !COREDUMP
i2c: imx: Fix external abort on interrupt in exit paths
ARM: samsung: fix PM debug build with DEBUG_LL but !MMU
ARM: s3c24xx: fix missing system reset
Lang Dai (1):
uio: free uio id after uio file node is freed
Li Jun (3):
usb: dwc3: core: add phy cleanup for probe error handling
usb: dwc3: core: don't trigger runtime pm when remove driver
usb: typec: tcpm: reset hard_reset_count for any disconnect
Luo Meng (1):
ext4: fix invalid inode checksum
Madhav Chauhan (1):
drm/amdgpu: don't map BO in reserved region
Madhuparna Bhowmik (2):
mmc: via-sdmmc: Fix data race bug
drivers: watchdog: rdc321x_wdt: Fix race condition bugs
Mahesh Salgaonkar (1):
powerpc/powernv/elog: Fix race while processing OPAL error log event.
Marc Zyngier (2):
arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
KVM: arm64: Fix AArch32 handling of DBGD{CCINT, SCRext} and DBGVCR
Marek Behún (1):
leds: bcm6328, bcm6358: use devres LED registering function
Martin Fuzzey (1):
w1: mxc_w1: Fix timeout resolution problem leading to bus error
Masahiro Fujiwara (1):
gtp: fix an use-before-init in gtp_newlink()
Masami Hiramatsu (1):
ia64: kprobes: Use generic kretprobe trampoline handler
Mateusz Nosek (1):
futex: Fix incorrect should_fail_futex() handling
Matthew Wilcox (Oracle) (3):
ceph: promote to unsigned long long before shifting
9P: Cast to loff_t before multiplying
cachefiles: Handle readpage error correctly
Michael Chan (1):
bnxt_en: Log unknown link speed appropriately.
Michael Neuling (1):
powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load
emulation
Michael Schaller (1):
efivarfs: Replace invalid slashes with exclamation marks in dentries.
Miklos Szeredi (1):
fuse: fix page dereference after free
Nadezda Lutovinova (1):
drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working
correctly
Nicholas Piggin (3):
mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
Nick Desaulniers (1):
arm64: link with -z norelro regardless of CONFIG_RELOCATABLE
Olga Kornievskaia (1):
NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
Oliver Neukum (1):
USB: adutux: fix debugging
Oliver O'Halloran (1):
powerpc/powernv/smp: Fix spurious DBG() warning
Paul Cercueil (1):
dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
Peter Chen (1):
usb: xhci: omit duplicate actions when suspending a runtime suspended
host.
Peter Zijlstra (1):
serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
Qiujun Huang (1):
ring-buffer: Return 0 on success from ring_buffer_resize()
Qu Wenruo (1):
btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
Quinn Tran (1):
scsi: qla2xxx: Fix crash on session cleanup with unload
Raju Rangoju (1):
cxgb4: set up filter action after rewrites
Ran Wang (1):
usb: host: fsl-mph-dr-of: check return of dma_set_mask()
Randy Dunlap (1):
x86/PCI: Fix intel_mid_pci.c build error when ACPI is not enabled
Rasmus Villemoes (1):
scripts/setlocalversion: make git describe output more reliable
Raul E Rangel (1):
mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
Ronnie Sahlberg (1):
cifs: handle -EINTR in cifs_setattr
Sandeep Singh (1):
usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
Sascha Hauer (1):
ata: sata_nv: Fix retrieving of active qcs
Sathishkumar Muruganandam (1):
ath10k: fix VHT NSS calculation when STBC is enabled
Song Liu (2):
bpf: Fix comment for helper bpf_current_task_under_cgroup()
md/raid5: fix oops during stripe resizing
Stefano Garzarella (1):
vringh: fix __vringh_iov() when riov and wiov are different
Sven Schnelle (1):
s390/stp: add locking to sysfs functions
Takashi Iwai (1):
drm/amd/display: Don't invoke kgdb_breakpoint() unconditionally
Tero Kristo (1):
clk: ti: clockdomain: fix static checker warning
Thinh Nguyen (2):
usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
usb: dwc3: gadget: Check MPS of the request length
Tom Rix (2):
video: fbdev: pvr2fb: initialize variables
media: tw5864: check status of tw5864_frameinterval_get
Tony Lindgren (1):
ARM: dts: omap4: Fix sgx clock rate for 4430
Tung Nguyen (1):
tipc: fix memory leak caused by tipc_buf_append()
Valentin Schneider (1):
arm64: topology: Stop using MPIDR for topology information
Vinay Kumar Yadav (3):
chelsio/chtls: fix deadlock issue
chelsio/chtls: fix memory leaks in CPL handlers
chelsio/chtls: fix tls record info to user
Wei Huang (1):
acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
Wen Gong (1):
ath10k: start recovery process when payload length exceeds max htc
length for sdio
Xia Jiang (1):
media: platform: Improve queue set up flow for bug fixing
Xie He (1):
drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
Xiongfeng Wang (1):
power: supply: test_power: add missing newlines when printing
parameters by sysfs
Xiubo Li (1):
nbd: make the config put is called before the notifying the waiter
Yoshihiro Shimoda (1):
arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC
nodes
Zhang Qilong (1):
f2fs: add trace exit in exception path
Zhao Heming (1):
md/bitmap: md_bitmap_get_counter returns wrong blocks
Zhengyuan Liu (1):
arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
Zhihao Cheng (2):
ubifs: dent: Fix some potential memory leaks while iterating entries
ubi: check kthread_should_stop() after the setting of task state
Zong Li (1):
riscv: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
dmitry.torokhov(a)gmail.com (1):
ACPI: button: fix handling lid state changes when input device closed
Documentation/filesystems/fscrypt.rst | 12 +-
.../media/uapi/v4l/colorspaces-defs.rst | 9 +-
.../media/uapi/v4l/colorspaces-details.rst | 5 +-
Makefile | 2 +-
arch/Kconfig | 7 +
arch/arm/Kconfig | 2 +
arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 1 +
arch/arm/boot/dts/omap4.dtsi | 2 +-
arch/arm/boot/dts/omap443x.dtsi | 10 ++
arch/arm/boot/dts/s5pv210.dtsi | 127 +++++++--------
arch/arm/kernel/hw_breakpoint.c | 100 ++++++++----
arch/arm/plat-samsung/Kconfig | 1 +
arch/arm64/Kconfig.platforms | 1 +
arch/arm64/Makefile | 4 +-
arch/arm64/boot/dts/renesas/ulcb.dtsi | 1 +
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/include/asm/numa.h | 3 +
arch/arm64/kernel/cpu_errata.c | 8 +
arch/arm64/kernel/topology.c | 43 ++---
arch/arm64/kvm/sys_regs.c | 6 +-
arch/arm64/mm/numa.c | 6 +-
arch/ia64/kernel/Makefile | 2 +-
arch/ia64/kernel/kprobes.c | 77 +--------
arch/powerpc/Kconfig | 14 ++
arch/powerpc/include/asm/drmem.h | 4 +-
arch/powerpc/include/asm/mmu_context.h | 2 +-
arch/powerpc/kernel/rtas.c | 153 ++++++++++++++++++
arch/powerpc/kernel/sysfs.c | 42 ++---
arch/powerpc/kernel/traps.c | 2 +-
arch/powerpc/platforms/powernv/opal-elog.c | 33 +++-
arch/powerpc/platforms/powernv/smp.c | 2 +-
arch/riscv/include/uapi/asm/auxvec.h | 3 +
arch/s390/kernel/time.c | 118 ++++++++++----
arch/sparc/kernel/smp_64.c | 65 ++------
arch/um/kernel/sigio.c | 6 +-
arch/x86/events/amd/ibs.c | 53 ++++--
arch/x86/include/asm/msr-index.h | 1 +
arch/x86/kernel/unwind_orc.c | 9 +-
arch/x86/pci/intel_mid_pci.c | 1 +
arch/x86/xen/enlighten_pv.c | 9 ++
block/blk-core.c | 9 +-
drivers/acpi/acpi_dbg.c | 3 +
drivers/acpi/acpi_extlog.c | 6 +-
drivers/acpi/button.c | 13 +-
drivers/acpi/numa.c | 2 +-
drivers/acpi/video_detect.c | 9 ++
drivers/ata/sata_nv.c | 2 +-
drivers/ata/sata_rcar.c | 2 +-
drivers/base/core.c | 4 +-
drivers/block/nbd.c | 2 +-
drivers/bus/fsl-mc/mc-io.c | 7 +-
drivers/clk/ti/clockdomain.c | 2 +
drivers/cpufreq/acpi-cpufreq.c | 3 +-
drivers/cpufreq/sti-cpufreq.c | 6 +-
drivers/crypto/chelsio/chtls/chtls_cm.c | 29 ++--
drivers/crypto/chelsio/chtls/chtls_io.c | 7 +-
drivers/dma/dma-jz4780.c | 7 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 ++
drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +-
drivers/gpu/drm/amd/display/dc/os_types.h | 2 +-
.../bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 12 +-
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 9 +-
drivers/gpu/drm/i915/i915_drv.h | 6 +-
drivers/gpu/drm/ttm/ttm_bo.c | 2 +-
drivers/hid/wacom_wac.c | 4 +-
drivers/i2c/busses/i2c-imx.c | 24 +--
drivers/iio/adc/ti-adc0832.c | 11 +-
drivers/iio/adc/ti-adc12138.c | 13 +-
drivers/iio/gyro/itg3200_buffer.c | 15 +-
drivers/iio/light/si1145.c | 19 ++-
drivers/infiniband/core/addr.c | 11 +-
drivers/infiniband/hw/qedr/qedr_iw_cm.c | 1 +
drivers/input/serio/hil_mlc.c | 21 ++-
drivers/input/serio/hp_sdc_mlc.c | 8 +-
drivers/leds/leds-bcm6328.c | 2 +-
drivers/leds/leds-bcm6358.c | 2 +-
drivers/md/md-bitmap.c | 2 +-
drivers/md/raid5.c | 4 +-
drivers/media/i2c/imx274.c | 8 +-
drivers/media/pci/tw5864/tw5864-video.c | 6 +
.../media/platform/mtk-jpeg/mtk_jpeg_core.c | 7 +
drivers/media/usb/uvc/uvc_ctrl.c | 27 ++--
drivers/memory/emif.c | 33 +---
drivers/message/fusion/mptscsih.c | 13 +-
drivers/misc/cxl/pci.c | 4 +-
drivers/mmc/host/sdhci-acpi.c | 37 +++++
drivers/mmc/host/via-sdmmc.c | 3 +
drivers/mtd/ubi/wl.c | 13 ++
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +-
.../net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 56 ++++---
drivers/net/ethernet/chelsio/cxgb4/t4_tcb.h | 4 +
drivers/net/ethernet/mellanox/mlxsw/core.c | 5 +
drivers/net/ethernet/realtek/r8169.c | 4 +-
drivers/net/ethernet/renesas/ravb_main.c | 10 +-
drivers/net/gtp.c | 16 +-
drivers/net/wan/hdlc_fr.c | 98 +++++------
drivers/net/wireless/ath/ath10k/htt_rx.c | 8 +-
drivers/net/wireless/ath/ath10k/sdio.c | 4 +
drivers/net/wireless/intersil/p54/p54pci.c | 4 +-
drivers/nvme/host/rdma.c | 1 -
drivers/power/supply/bq27xxx_battery.c | 6 +-
drivers/power/supply/test_power.c | 6 +
drivers/rpmsg/qcom_glink_native.c | 6 +-
drivers/rtc/rtc-rx8010.c | 24 ++-
drivers/scsi/qla2xxx/qla_target.c | 13 +-
drivers/staging/comedi/drivers/cb_pcidas.c | 1 +
drivers/staging/octeon/ethernet-mdio.c | 6 -
drivers/staging/octeon/ethernet-rx.c | 34 ++--
drivers/staging/octeon/ethernet.c | 9 ++
drivers/tty/serial/amba-pl011.c | 11 +-
drivers/uio/uio.c | 4 +-
drivers/usb/class/cdc-acm.c | 12 +-
drivers/usb/class/cdc-acm.h | 3 +-
drivers/usb/dwc3/core.c | 15 +-
drivers/usb/dwc3/ep0.c | 11 +-
drivers/usb/dwc3/gadget.c | 4 +-
drivers/usb/host/fsl-mph-dr-of.c | 9 +-
drivers/usb/host/xhci-pci.c | 17 ++
drivers/usb/host/xhci.c | 7 +-
drivers/usb/host/xhci.h | 1 +
drivers/usb/misc/adutux.c | 1 +
drivers/usb/typec/tcpm.c | 8 +-
drivers/vhost/vringh.c | 9 +-
drivers/video/fbdev/pvr2fb.c | 2 +
drivers/w1/masters/mxc_w1.c | 14 +-
drivers/watchdog/rdc321x_wdt.c | 5 +-
drivers/xen/events/events_base.c | 27 +++-
drivers/xen/events/events_internal.h | 3 +-
fs/9p/vfs_file.c | 4 +-
fs/btrfs/ctree.c | 6 +
fs/btrfs/delayed-inode.c | 3 +-
fs/btrfs/dev-replace.c | 2 +-
fs/btrfs/reada.c | 2 +
fs/btrfs/send.c | 74 ++++++++-
fs/btrfs/tree-log.c | 8 +
fs/btrfs/volumes.c | 14 +-
fs/cachefiles/rdwr.c | 3 +-
fs/ceph/addr.c | 2 +-
fs/cifs/inode.c | 13 +-
fs/crypto/crypto.c | 58 +++----
fs/crypto/fname.c | 1 +
fs/crypto/hooks.c | 34 ++--
fs/crypto/policy.c | 3 +-
fs/dcache.c | 15 ++
fs/efivarfs/super.c | 3 +
fs/exec.c | 15 +-
fs/ext4/ext4.h | 62 +++++--
fs/ext4/inode.c | 11 +-
fs/ext4/namei.c | 76 ++++++---
fs/ext4/resize.c | 4 +-
fs/ext4/super.c | 6 +
fs/f2fs/checkpoint.c | 8 +-
fs/f2fs/dir.c | 8 +-
fs/f2fs/namei.c | 17 +-
fs/fuse/dev.c | 28 ++--
fs/gfs2/ops_fstype.c | 18 ++-
fs/nfs/namespace.c | 12 +-
fs/nfs/nfs4proc.c | 9 +-
fs/nfsd/nfsproc.c | 16 ++
fs/ubifs/debug.c | 1 +
fs/ubifs/dir.c | 8 +-
fs/udf/super.c | 21 ++-
fs/xfs/libxfs/xfs_bmap.c | 19 ++-
fs/xfs/xfs_rtalloc.c | 10 +-
include/linux/dcache.h | 2 +-
include/linux/fscrypt.h | 34 ++--
include/linux/fscrypt_notsupp.h | 9 +-
include/linux/fscrypt_supp.h | 6 +-
include/linux/hil_mlc.h | 2 +-
include/linux/mtd/pfow.h | 2 +-
include/linux/usb/pd.h | 1 +
include/uapi/linux/bpf.h | 4 +-
include/uapi/linux/nfs4.h | 3 +
include/uapi/linux/videodev2.h | 17 +-
init/Kconfig | 3 +-
kernel/debug/debug_core.c | 22 ++-
kernel/futex.c | 4 +-
kernel/trace/ring_buffer.c | 8 +-
lib/scatterlist.c | 2 +-
net/9p/trans_fd.c | 2 +-
net/ceph/messenger.c | 5 +
net/ipv4/tcp.c | 2 +
net/ipv4/tcp_input.c | 3 +-
net/sched/sch_netem.c | 9 +-
net/tipc/msg.c | 5 +-
scripts/setlocalversion | 21 ++-
tools/include/uapi/linux/bpf.h | 4 +-
tools/objtool/orc_gen.c | 33 +++-
tools/perf/util/print_binary.c | 2 +-
189 files changed, 1746 insertions(+), 928 deletions(-)
--
2.25.1
1
174
[PATCH 1/5] partitions/efi: Fix partition name parsing in GUID partition entry
by Yang Yingliang 16 Nov '20
by Yang Yingliang 16 Nov '20
16 Nov '20
From: Nikolai Merinov <n.merinov(a)inango-systems.com>
mainline inclusion
from mainline-5.7-rc1
commit d5528d5e91041e68e8eab9792ce627705a0ed273
category: bugfix
bugzilla: 32454
CVE: NA
---------------------------
GUID partition entry defined to have a partition name as 36 UTF-16LE
code units. This means that on big-endian platforms ASCII symbols
would be read with 0xXX00 efi_char16_t character code. In order to
correctly extract ASCII characters from a partition name field we
should be converted from 16LE to CPU architecture.
The problem exists on all big endian platforms.
[ mingo: Minor edits. ]
Fixes: eec7ecfede74 ("genhd, efi: add efi partition metadata to hd_structs")
Reviewed-by: Christoph Hellwig <hch(a)lst.de>
Signed-off-by: Nikolai Merinov <n.merinov(a)inango-systems.com>
Signed-off-by: Ard Biesheuvel <ardb(a)kernel.org>
Signed-off-by: Ingo Molnar <mingo(a)kernel.org>
Link: https://lore.kernel.org/r/20200308080859.21568-29-ardb@kernel.org
Link: https://lore.kernel.org/r/797777312.1324734.1582544319435.JavaMail.zimbra@i…
Signed-off-by: yangerkun <yangerkun(a)huawei.com>
Reviewed-by: Yufen Yu <yuyufen(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
block/partitions/efi.c | 35 ++++++++++++++++++++++++++---------
block/partitions/efi.h | 2 +-
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 39f70d968754..b9beaa0a9b36 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -670,6 +670,31 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
return 0;
}
+/**
+ * utf16_le_to_7bit(): Naively converts a UTF-16LE string to 7-bit ASCII characters
+ * @in: input UTF-16LE string
+ * @size: size of the input string
+ * @out: output string ptr, should be capable to store @size+1 characters
+ *
+ * Description: Converts @size UTF16-LE symbols from @in string to 7-bit
+ * ASCII characters and stores them to @out. Adds trailing zero to @out array.
+ */
+static void utf16_le_to_7bit(const __le16 *in, unsigned int size, u8 *out)
+{
+ unsigned int i = 0;
+
+ out[size] = 0;
+
+ while (i < size) {
+ u8 c = le16_to_cpu(in[i]) & 0xff;
+
+ if (c && !isprint(c))
+ c = '!';
+ out[i] = c;
+ i++;
+ }
+}
+
/**
* efi_partition(struct parsed_partitions *state)
* @state: disk parsed partitions
@@ -706,7 +731,6 @@ int efi_partition(struct parsed_partitions *state)
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
struct partition_meta_info *info;
- unsigned label_count = 0;
unsigned label_max;
u64 start = le64_to_cpu(ptes[i].starting_lba);
u64 size = le64_to_cpu(ptes[i].ending_lba) -
@@ -727,14 +751,7 @@ int efi_partition(struct parsed_partitions *state)
/* Naively convert UTF16-LE to 7 bits. */
label_max = min(ARRAY_SIZE(info->volname) - 1,
ARRAY_SIZE(ptes[i].partition_name));
- info->volname[label_max] = 0;
- while (label_count < label_max) {
- u8 c = ptes[i].partition_name[label_count] & 0xff;
- if (c && !isprint(c))
- c = '!';
- info->volname[label_count] = c;
- label_count++;
- }
+ utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname);
state->parts[i + 1].has_info = true;
}
kfree(ptes);
diff --git a/block/partitions/efi.h b/block/partitions/efi.h
index abd0b19288a6..42db2513ecfa 100644
--- a/block/partitions/efi.h
+++ b/block/partitions/efi.h
@@ -102,7 +102,7 @@ typedef struct _gpt_entry {
__le64 starting_lba;
__le64 ending_lba;
gpt_entry_attributes attributes;
- efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
+ __le16 partition_name[72/sizeof(__le16)];
} __packed gpt_entry;
typedef struct _gpt_mbr_record {
--
2.25.1
1
4
14 Nov '20
hulk inclusion
category: feature
feature: digest-lists
---------------------------
The EVM ignore mode works similarly to the metadata modification mode. They
both allow an operation to be performed even if the operation causes
metadata to become invalid.
Currently, evm_reset_status() notifies to IMA that an operation modified
metadata only when the metadata modification mode was chosen. With this
patch, evm_reset_status() does the same also when the EVM ignore mode is
selected.
Signed-off-by: Roberto Sassu <roberto.sassu(a)huawei.com>
---
security/integrity/evm/evm_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 5155ff4c4ef2..2d3c1670d8d3 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -570,7 +570,8 @@ static void evm_reset_status(struct inode *inode, int bit)
iint = integrity_iint_find(inode);
if (iint) {
- if (evm_initialized & EVM_ALLOW_METADATA_WRITES)
+ if ((evm_initialized & EVM_ALLOW_METADATA_WRITES) ||
+ evm_ignoremode)
set_bit(bit, &iint->atomic_flags);
iint->evm_status = INTEGRITY_UNKNOWN;
--
2.27.GIT
1
1
2
3